leetcode
leetcode 2651 ~ 2700
相等的有理数

相等的有理数

难度:

标签:

题目描述

Given two strings s and t, each of which represents a non-negative rational number, return true if and only if they represent the same number. The strings may use parentheses to denote the repeating part of the rational number.

A rational number can be represented using up to three parts: <IntegerPart>, <NonRepeatingPart>, and a <RepeatingPart>. The number will be represented in one of the following three ways:

  • <IntegerPart>
    • For example, 12, 0, and 123.
  • <IntegerPart><.><NonRepeatingPart>
    • For example, 0.5, 1., 2.12, and 123.0001.
  • <IntegerPart><.><NonRepeatingPart><(><RepeatingPart><)>
    • For example, 0.1(6), 1.(9), 123.00(1212).

The repeating portion of a decimal expansion is conventionally denoted within a pair of round brackets. For example:

  • 1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66).

 

Example 1:

Input: s = "0.(52)", t = "0.5(25)"
Output: true
Explanation: Because "0.(52)" represents 0.52525252..., and "0.5(25)" represents 0.52525252525..... , the strings represent the same number.

Example 2:

Input: s = "0.1666(6)", t = "0.166(66)"
Output: true

Example 3:

Input: s = "0.9(9)", t = "1."
Output: true
Explanation: "0.9(9)" represents 0.999999999... repeated forever, which equals 1.  [See this link for an explanation.]
"1." represents the number 1, which is formed correctly: (IntegerPart) = "1" and (NonRepeatingPart) = "".

 

Constraints:

  • Each part consists only of digits.
  • The <IntegerPart> does not have leading zeros (except for the zero itself).
  • 1 <= <IntegerPart>.length <= 4
  • 0 <= <NonRepeatingPart>.length <= 4
  • 1 <= <RepeatingPart>.length <= 4

代码结果

运行时间: 30 ms, 内存: 16.1 MB


/*
 * The problem requires us to compare two strings that represent rational numbers,
 * possibly with repeating decimal parts, and determine if they represent the same number.
 * The approach involves converting these rational numbers to their decimal representations
 * and comparing these representations using Java Stream API.
 */

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class RationalNumberComparisonStream {
    public boolean isRationalEqual(String s, String t) {
        return convertToDecimal(s).equals(convertToDecimal(t));
    }

    private String convertToDecimal(String s) {
        if (!s.contains("(")) {
            return s;
        }
        String[] parts = s.split("[.()]");
        String integerPart = parts[0];
        String nonRepeatingPart = parts.length > 1 ? parts[1] : "";
        String repeatingPart = parts.length == 3 ? parts[2] : "";
        String repeatedSequence = IntStream.range(0, 20)
                .mapToObj(i -> repeatingPart)
                .collect(Collectors.joining());
        return integerPart + "." + nonRepeatingPart + repeatedSequence;
    }
}

解释

方法:

题解的思路是将给定的有理数字符串转换为精确的数学表示形式,使用 Python 的分数模块。这种转换处理了整数部分、非重复小数部分和重复小数部分。首先,根据小数点划分整数和小数部分。如果存在括号,则进一步将非重复和重复小数部分区分开来。对于非重复小数部分,直接将其转换为相应的分数。对于重复小数部分,根据无限循环小数的数学性质转换为分数。最后,比较两个数的分数表示是否相等。

时间复杂度:

O(log(max(a, b)))

空间复杂度:

O(1)

代码细节讲解

🦆
在处理有理数字符串时,如何确保转换的准确性,尤其是当小数部分和重复小数部分非常长时?
为确保有理数字符串的准确转换,尤其是在处理较长的小数部分和重复小数部分时,首先需要确保输入字符串的格式正确无误。Python的`int`和`Fraction`类在处理大数字时具有很好的性能,因为Python的整数和分数操作是任意精度的。此外,`Fraction`类会自动化简分数,从而减少计算复杂度和提高精度。在实际应用中,还应考虑增加错误处理机制来应对格式错误或异常数据输入的情况,如进行输入验证和格式化检查。
🦆
在解析和转换有理数时,如果有理数的格式不符合预期(例如缺失括号或多余的字符),题解中的方法如何应对这种情况?
题解中的方法没有直接包含错误处理逻辑来应对格式错误如缺失括号或包含多余字符的情况。因此,为提高代码的健壮性,应该在处理之前添加输入验证。这包括检查字符串是否包含非法字符、是否有匹配的括号以及小数点的位置是否合理。如果发现任何格式错误,应该抛出异常或返回错误消息,避免进行错误的数学计算。
🦆
为什么在转换重复小数部分时使用的分数公式是 `Fraction(int(r), (10**len(r) - 1) * 10**len(n))`?这个公式背后的数学原理是什么?
这个分数公式的使用是基于无限循环小数转换为分数的数学原理。考虑一个有理数的重复小数部分`r`和非重复小数部分`n`。假设`r`是重复序列,例如对于0.00123(456),`r`是456。将这个无限重复序列表示为分数时,我们可以将其视为几何级数的求和。级数的每一项都是重复序列的一个副本,后一项比前一项小10的`r`的长度次方。因此,这个级数可以表示为`r / (10^len(r) - 1)`,乘以`10^len(n)`是为了将小数点移动到正确的位置。所以,完整的分数表示是`Fraction(int(r), (10**len(r) - 1) * 10**len(n))`,它精确地表示了无限循环小数部分的值。

相关问题