加载中...
972-相等的有理数(Equal Rational Numbers)
发表于:2021-12-03 | 分类: 困难
字数统计: 1.6k | 阅读时长: 8分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/equal-rational-numbers

英文原文

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>
    <ul>
        <li>For example, <code>12</code>, <code>0</code>, and <code>123</code>.</li>
    </ul>
    </li>
    <li><code>&lt;IntegerPart&gt;<strong>&lt;.&gt;</strong>&lt;NonRepeatingPart&gt;</code>
    <ul>
        <li>For example, <code>0.5</code>, <code>1.</code>, <code>2.12</code>, and <code>123.0001</code>.</li>
    </ul>
    </li>
    <li><code>&lt;IntegerPart&gt;<strong>&lt;.&gt;</strong>&lt;NonRepeatingPart&gt;<strong>&lt;(&gt;</strong>&lt;RepeatingPart&gt;<strong>&lt;)&gt;</strong></code>
    <ul>
        <li>For example, <code>0.1(6)</code>, <code>1.(9)</code>, <code>123.00(1212)</code>.</li>
    </ul>
    </li>
    

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

中文题目

给定两个字符串 ST,每个字符串代表一个非负有理数,只有当它们表示相同的数字时才返回 true;否则,返回 false。字符串中可以使用括号来表示有理数的重复部分。

通常,有理数最多可以用三个部分来表示:整数部分 <IntegerPart>小数非重复部分 <NonRepeatingPart> 和小数重复部分 <(><RepeatingPart><)>。数字可以用以下三种方法之一来表示:

  • <IntegerPart>(例:0,12,123)
  • <IntegerPart><.><NonRepeatingPart> (例:0.5,2.12,2.0001)
  • <IntegerPart><.><NonRepeatingPart><(><RepeatingPart><)>(例:0.1(6),0.9(9),0.00(1212))

十进制展开的重复部分通常在一对圆括号内表示。例如:

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

0.1(6) 或 0.1666(6) 或 0.166(66) 都是 1 / 6 的正确表示形式。

 

示例 1:

输入:S = "0.(52)", T = "0.5(25)"
输出:true
解释:因为 "0.(52)" 代表 0.52525252...,而 "0.5(25)" 代表 0.52525252525.....,则这两个字符串表示相同的数字。

示例 2:

输入:S = "0.1666(6)", T = "0.166(66)"
输出:true

示例 3:

输入:S = "0.9(9)", T = "1."
输出:true
解释:
"0.9(9)" 代表 0.999999999... 永远重复,等于 1 。[有关说明,请参阅此链接]
"1." 表示数字 1,其格式正确:(IntegerPart) = "1" 且 (NonRepeatingPart) = "" 。

 

提示:

  1. 每个部分仅由数字组成。
  2. 整数部分 <IntegerPart> 不会以 2 个或更多的零开头。(对每个部分的数字没有其他限制)。
  3. 1 <= <IntegerPart>.length <= 4
  4. 0 <= <NonRepeatingPart>.length <= 4
  5. 1 <= <RepeatingPart>.length <= 4

通过代码

官方题解

方法:分数类

思路

因为给定的两个数字都表示一个分数,所以我们需要一个分数类去处理这两个分数。它应该能帮助我们将两个分数加起来,并且保证答案为最简形式。

算法

我们需要理解给定的两个分数,最困难的问题是如何表示它们。

比如说我们有一个字符串 S = "0.(12)"。它代表(定义 $r = \frac{1}{100}$):

$$
S = \frac{12}{100} + \frac{12}{10000} + \frac{12}{10^6} + \frac{12}{10^8} + \frac{12}{10^{10}} + \cdots
$$

$$
S = 12 * (r + r^2 + r^3 + \cdots)
$$

$$
S = 12 * \frac{r}{1-r}
$$

其中 $(r + r^2 + r^3 + \cdots)$ 是一个等比数列求和问题。

总而言之,对于长度为 $k$ 的重复部分 $x$,会对答案有 $\frac{xr}{1-r}$ 的贡献,其中 $r = 10^{-k}$。

另外两部分就更容易计算了,因为它们仅仅是对数值的简单翻译。

[QFRcSJ8K-Java]
class Solution { public boolean isRationalEqual(String S, String T) { Fraction f1 = convert(S); Fraction f2 = convert(T); return f1.n == f2.n && f1.d == f2.d; } public Fraction convert(String S) { int state = 0; //whole, decimal, repeating Fraction ans = new Fraction(0, 1); int decimal_size = 0; for (String part: S.split("[.()]")) { state++; if (part.isEmpty()) continue; long x = Long.valueOf(part); int sz = part.length(); if (state == 1) { // whole ans.iadd(new Fraction(x, 1)); } else if (state == 2) { // decimal ans.iadd(new Fraction(x, (long) Math.pow(10, sz))); decimal_size = sz; } else { // repeating long denom = (long) Math.pow(10, decimal_size); denom *= (long) (Math.pow(10, sz) - 1); ans.iadd(new Fraction(x, denom)); } } return ans; } } class Fraction { long n, d; Fraction(long n, long d) { long g = gcd(n, d); this.n = n / g; this.d = d / g; } public void iadd(Fraction other) { long numerator = this.n * other.d + this.d * other.n; long denominator = this.d * other.d; long g = Fraction.gcd(numerator, denominator); this.n = numerator / g; this.d = denominator / g; } static long gcd(long x, long y) { return x != 0 ? gcd(y % x, x) : y; } }
[QFRcSJ8K-Python]
from fractions import Fraction class Solution(object): def isRationalEqual(self, S, T): def convert(S): if '.' not in S: return Fraction(int(S), 1) i = S.index('.') ans = Fraction(int(S[:i]), 1) S = S[i+1:] if '(' not in S: if S: ans += Fraction(int(S), 10 ** len(S)) return ans i = S.index('(') if i: ans += Fraction(int(S[:i]), 10 ** i) S = S[i+1:-1] j = len(S) ans += Fraction(int(S), 10**i * (10**j - 1)) return ans return convert(S) == convert(T)

复杂度分析

  • 时间复杂度:$O(1)$,因为字符串 $S, T$ 的长度可以看作是 $O(1)$ 级别的。

  • 空间复杂度:$O(1)$。

统计信息

通过次数 提交次数 AC比率
1338 3297 40.6%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
970-强整数(Powerful Integers)
下一篇:
971-翻转二叉树以匹配先序遍历(Flip Binary Tree To Match Preorder Traversal)
本文目录
本文目录