链接:https://leetcode.cn/problems/nth-magical-number/solutions/1984767/er-fen-cao-zuo-zhu-shi-chao-ji-xiang-xi-5nfti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目
思路
按照题目意思直接暴力枚举,a和b的所有倍数,然后取 第 n 个 倍数即可,但是 n 有 10^9 次大小,肯定是会超的,所以需要优化时间。
从两个方面进行优化:
- a 和 b 的所有倍数是不是都需要枚举出来?
- 其实是不需要的,我们只需要第 n 个数据,其中的我们并不关心,那么我们可以 对 a 和 b 进行对应的乘积,a * n 则存在 n+1 个有效元素, b * n 也存在 n+1 个元素
- 那么现在是不是存在 2n + 2 个 有效元素呢?
- 并不是 这些数据中还存在 a 和 b 的公倍数是 重复计算的, 比如 a = 2, b = 3, 那么 6 就是a和b的计算进去的有效元素,需要去掉,当然在实际计算过程中我们只需要 n + 1 个有效元素即可,所有取 a,b中最小的元素 * n。当然取全部也没问题,只是计算量大小问题
- 那么现在是不是存在 2n + 2 个 有效元素呢?
- 其实是不需要的,我们只需要第 n 个数据,其中的我们并不关心,那么我们可以 对 a 和 b 进行对应的乘积,a * n 则存在 n+1 个有效元素, b * n 也存在 n+1 个元素
- 寻找第 n 个 倍数 的时候 是否 需要从头开始检索每一个倍数元素?
- 我们现在已经知道了 前 2n + 2 个元素了,如果从头开始寻找第 n个元素 肯定是不行的,那么有没有比较快的查找算法呢?
- 二分查找 二分操作边界情况分析
- 设答案为 x,循环结束时,≤x 的神奇数字有 n 个,而 ≤x−1 的神奇数字不足 n 个。只有当 x 是一个神奇数字时,才会出现这种情况。
- 我们现在已经知道了 前 2n + 2 个元素了,如果从头开始寻找第 n个元素 肯定是不行的,那么有没有比较快的查找算法呢?
代码
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int gcd(int a, int b) {
return b != 0 ? gcd(b, a % b) : a;
}
int lcm(int a, int b) {//辗转相除法
return a * b / gcd(a, b);
}
int nthMagicalNumber(int n, int a, int b) {
const int MOD = 1e9 + 7;
long left = MIN(a, b);
long right = (long) n * MIN(a, b);//左右边界
int c = lcm(a, b);
while (left <= right) {//二分查找
long mid = (left + right) / 2;
long cnt = mid / a + mid / b - mid / c;//当前有效元素的个数
if (cnt >= n) {
right = mid - 1;// 范围缩小到 [left, mid]
} else {
left = mid + 1;// 范围缩小到 [mid, right]
}
}
return (right + 1) % MOD;
}
作者:小迅
链接:https://leetcode.cn/problems/nth-magical-number/solutions/1984767/er-fen-cao-zuo-zhu-shi-chao-ji-xiang-xi-5nfti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
const long MOD = 1e9 + 7;
public:
int nthMagicalNumber(int n, int a, int b) {
long lcm = std::lcm(a, b);
long left = 0, right = (long) min(a, b) * n; //左闭右闭 [left, right]
while (left <= right) { // 开区间不为空
long mid = left + (right - left) / 2;
if (mid / a + mid / b - mid / lcm >= n)
right = mid - 1; // 范围缩小到 [left, mid]
else
left = mid + 1; // 范围缩小到 [mid, right]
}
return (right + 1) % MOD;
}
};
作者:小迅
链接:https://leetcode.cn/problems/nth-magical-number/solutions/1984767/er-fen-cao-zuo-zhu-shi-chao-ji-xiang-xi-5nfti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。