LeetCode1447.最简分数
给你一个整数 n n n ,请你返回所有 0 0 0 到 1 1 1 之间(不包括 0 0 0 和 1 1 1)满足分母小于等于 n n n 的 最简分数 。分数可以以任意顺序返回。
示例 1:
输入:n = 2
输出:[“1/2”]
解释:“1/2” 是唯一一个分母小于等于 2 的最简分数。
题目分析
这道题目可以拆解成为两部分.
- 如何确定最简分数
- 如何返回结果的形式
具体解析通过下一小节知识点总结.
知识点总结
辗转相除法
想要找到最终中间所有的最简的分数,那么分子和分母需要满足不可约分.
两个数字
n
u
m
1
num1
num1 和
n
u
m
2
num2
num2 不可约分等价于
n
u
m
1
num1
num1 和
n
u
m
2
num2
num2 的最大公约数为 1.
也就是说它们两个不能同时被除
1
1
1 以外的任何数字整除.(否则就能够被约分了!)
问题也就转换成为如何判断两个数字的最大公约数gcd
定理: 对于两个正整数
a
a
a,
b
b
b,满足
a
a
a >
b
b
b, 有
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a, b) = gcd(b, a\%b)
gcd(a,b)=gcd(b,a%b)成立
证明: 假设
a
=
k
∗
b
+
r
a =k* b + r
a=k∗b+r,则有
r
=
a
%
b
r = a \% b
r=a%b,同时
r
=
a
−
k
∗
b
r = a - k * b
r=a−k∗b
假设
d
d
d 是
a
a
a,
b
b
b 的最大公约数,那么
d
d
d 也是
r
r
r 的一个约数.
所以
d
d
d 也是
b
b
b 和
r
r
r 的最大公约数
∵ a = x ∗ d a = x * d a=x∗d, b = y ∗ d b = y * d b=y∗d
∴ r = a − k ∗ b = x ∗ d − y ∗ d = ( x − y ) ∗ d r = a - k * b = x * d - y * d = (x - y) * d r=a−k∗b=x∗d−y∗d=(x−y)∗d
备注: a a a > b b b --> x − y > 0 x - y > 0 x−y>0
代码实现:
func gcd(a, b int) int {
for b != 0 {
b, a = a % b, b
}
return a
}
数字转字符串
strconv.Itoa(num)
Go代码实现
func simplifiedFractions(n int) (ans []string) {
for denominator := 2; denominator <= n; denominator++ {
for numerator := 1; numerator < denominator; numerator++ {
if gcd(numerator, denominator) == 1 {
ans = append(ans, strconv.Itoa(numerator)+"/"+strconv.Itoa(denominator))
}
}
}
return
}
func gcd(a, b int) int {
for b != 0 {
b, a = a % b, b
}
return a
}