一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
题目
给你一个整数 n ,请你返回所有 0 到 1 之间(不包括 0 和 1)满足分母小于等于 n 的 最简 分数 。分数可以以 任意 顺序返回。
示例 1:
输入:n = 2
输出:["1/2"]
解释:"1/2" 是唯一一个分母小于等于 2 的最简分数。
示例 2:
输入:n = 3
输出:["1/2","1/3","2/3"]
示例 3:
输入:n = 4
输出:["1/2","1/3","1/4","2/3","3/4"]
解释:"2/4" 不是最简分数,因为它可以化简为 "1/2" 。
示例 4:
输入:n = 1
输出:[]
提示:
1 <= n <= 100
思考
本题难度中等。题目要求的是返回所有 0 到 1 之间(不包括 0 和 1)满足分母小于等于 n 的 最简分数。
由于分数是处于 (0,1) 的范围内,我们可以枚举分母 i∈[2,n] 和分子 j∈[1,i)的所有组合,判断分子分母的最大公约数是否为 1,若是则我们找到了一个最简分数。
求分子分母的最大公约数,我们可以通过**辗转相除法(也叫欧几里得算法)**去计算,这是很有意思的算法,每次迭代中判断余数是否为0,不为0则使用除数和余数继续迭代。
解答
方法一:数学
/**
* @param {number} n
* @return {string[]}
*/
var simplifiedFractions = function(n) {
let ans = []
for (let i = 2; i <= n; i++) {
for (let j = 1; j < i; j++) {
if (gcd(i, j) == 1) {
ans.push(`${j}/${i}`)
}
}
}
return ans
}
// 求最大公约数
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b))
// 执行用时:92 ms, 在所有 JavaScript 提交中击败了75.02%的用户
// 内存消耗:47.6 MB, 在所有 JavaScript 提交中击败了47.45%的用户
// 通过测试用例:100 / 100
复杂度分析
- 时间复杂度:
O(n^2*logn)。枚举分子分母的组合为O(n^2),每对分子分母计算最大公因数和生成字符串的复杂度均为O(logn)。 - 空间复杂度:O(1)。