[プログラミングの質問]醜い数Ⅲ:バイナリ検索、最大公約数、最小公倍数アルゴリズムを含む

1.タイトル:
n番目の醜い数を見つけるプログラムの設計を手伝ってください。醜い数は、aまたはbまたはcで割り切れる正の整数です。

示例 :
输入:n = 3, a = 2, b = 3, c = 5
输出:4
解释:丑数序列为 2, 3, 4, 5, 6, 8, 9, 10... 其中第 3 个是 4。
提示:1 <= n, a, b, c <= 10^9

2.考える:
まず第一に、なぜ二分法を最初に考えることができるのですか?
トピックを見てみましょう。最終状態(n)の範囲が非常に広いことがわかります。下から上に再帰するか、通常のトップダウンのバックトラッキングを実行しようとすると、明らかにタイムアウトします(動的プログラミング、DFSなど)。このような大きな状態空間に直面すると、二分法の時間の複雑さがlogNになるため、大幅に圧縮できます。トラバースする状態の数。
sum(状況例)= X / a + X / b + X / c-X / MCM_a_b-X / MCM_a_c-X / MCM_b_c + X / MCM_a_b_c、MCM +添え字を使用して最小公倍数を示します。
特定のアイデアは盗用されず、元のリンクが投稿されています:Alfeim問題解決のアイデア

3. C ++コード:
最大公約数と最小公倍数のアルゴリズムに注意してください

class Solution {
    
    
public:
    using LL = long long; // 使用using定义类型别名
    int nthUglyNumber(int n, int a, int b, int c) {
    
    
        LL start = min(min(a,b), c);
        LL end = start*n;

        LL MCM_a_b = LCM(a,b); //求最小公倍数
        LL MCM_a_c = LCM(a,c);
        LL MCM_b_c = LCM(b,c);
        LL MCM_a_b_c = LCM(MCM_a_b,c);

        LL res = Binary_Search( start, end, a, b, c, n, MCM_a_b, MCM_a_c, MCM_b_c, MCM_a_b_c );

        return res - min(min(res%a, res%b),res%c);
    }

// 二分查找
    LL Binary_Search(LL start, LL end, int a, int b, int c, int n, LL MCM_a_b, LL MCM_a_c, LL MCM_b_c, LL MCM_a_b_c) {
    
    
        if(start >= end) return start;

        LL mid = (end+start) >> 1; //移位代替除以2
        LL res = mid/a + mid/b + mid/c - mid/MCM_a_b - mid/MCM_a_c - mid/MCM_b_c + mid/MCM_a_b_c;
        if(res == n) 
            return mid;
        else if (res<n) {
    
    
            return Binary_Search( mid+1, end, a, b, c, n, MCM_a_b, MCM_a_c, MCM_b_c, MCM_a_b_c );
        }
        else
            return Binary_Search( start, mid-1, a, b, c, n, MCM_a_b, MCM_a_c, MCM_b_c, MCM_a_b_c );
    }

    LL LCM(LL a, LL b) {
    
     // 求最小公倍数
        LL multi = a * b;
        while(b > 0){
    
     //最小公倍数 = a*b/(a和b的最大公约数),最大公约数可以通过辗转相除法得到。
            LL tmp = a % b;
            a = b;
            b = tmp;
        } //循环结束后a为最大公约数
        LL res = multi / a;
        return res;
    }
};

参照:
トピックソース:滞在ボタン(LeetCode)
トピックリンク:https://leetcode-cn.com/problems/ugly-number-iii
問題解決著者:Alfeim
解決リンク:https://leetcode-cn.com/問題/ ugly-number-iii / solution / er-fen-fa-si-lu-pou-xi-by-alfeim /

総括する:

1.最大公約数は、トスとターンで割って得られます。
2.最小公倍数= a * b /(aとbの最大公約数)。

おすすめ

転載: blog.csdn.net/qq_33726635/article/details/106093974