力扣1201 丑数III
关键词:cpp,lambda
标签:二分查找
给你四个整数:n 、a 、b 、c ,请你设计一个算法来找出第 n 个丑数。
丑数是可以被 a 或 b 或 c 整除的 正整数 。
class Solution {
public:
int nthUglyNumber(int n, int a, int b, int c) {
int i=2;
while(i<INT_MAX){
if(i%a==0 || i%b==0 ||i%c==0) --n;
if(n==0) return i;
++i;
}
return i;
// 这里用 lambda 捕获计算好的最小公倍数,避免重复计算
const auto countLessEqual = [=] (long long x) -> long long {
return x / la + x / lb + x / lc - x / lab - x / lac - x / lbc + x / labc;
};
}
};
由于遍历绝对会超时所以需要转换思路
但必须要知道某个数是第几个“丑数”
寻找得知丑数编号的方法,即知道其前方有多少个丑数
class Solution {
public:
int nthUglyNumber(int n, int a, int b, int c) {
const long long la = a;
const long long lb = b;
const long long lc = c;
const long long lab = lcm(la, lb);
const long long lac = lcm(la, lc);
const long long lbc = lcm(lb, lc);
const long long labc = lcm(lab, lc);
const long long maxabc = max({a, b, c});
// 这里用 lambda 捕获计算好的最小公倍数,避免重复计算
const auto countLessEqual = [=] (long long x) -> long long {
return x / la + x / lb + x / lc - x / lab - x / lac - x / lbc + x / labc;
};
const long long m = countLessEqual(labc);
const long long q = n / m, r = n % m;
long long hi = min(labc, r * maxabc);
long long lo = 0;
while (lo < hi) {
const long long mi = (lo + hi) / 2;
if (countLessEqual(mi) < r)
lo = mi + 1;
else hi = mi;
}
return lo + q * labc;
}
};