LeetCode探索(54):1447-最简分数

229 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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)。

参考