【ルーキートレーニング】ソードフィンガーオファー14.ロープを切る

タイトル説明:

これが長さnのロープです。ロープを整数の長さのm個のセグメントに切断してください(mとnは整数、n> 1とm> 1)。各ロープの長さはk [0]、k [1です。 ] ... k [m-1]。k [0] k [1] …* k [m-1]の可能な最大の積は何ですか?たとえば、ロープの長さが8の場合、2、3、3の長さで3つに切断します。この時点で得られる最大の積は18です。

例1:
入力:2
出力:1
説明:2 = 1 + 1、1×1 = 1

例2:
入力:10
出力:36
説明:10 = 3 + 3 + 4、3 ×3×4 = 36
ヒント:
2 <= n <= 58
ソース:LeetCode
リンク:https:// leetcode-cnの
著作権.com / problem / jian-sheng-zi-lcofLingkouNetworkに属しています。商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。

問題解決のアイデア:

それがm個の部分に分割されていると仮定すると、質問の要件は、
MAX(a(1)a(2)a(m))が
既知であり、n = a(1)+ a(2)+…を見つけることです。 + a(m)

では、傍受するとき、傍受後の各セグメントの長さを最大化するにはどうすればよいでしょうか。
算術幾何平均の不等式から、次のことがわかります。
他の人からの引用

同じ長さの複数のセグメントに分割すると、製品が最大になります。
もちろん、1つのサブセクションに分割することはできません。

次に、各段落の長さが等しく、1に等しくないと仮定することもできます。

ここに画像の説明を挿入

上記の証明から、毎回3の長さをカットすると、得られる最終製品が最大であることがわかります。しかし、実際には、最終的にすべての等しい部分をカットできない可能性があるため、3つの状況があります。つまり、最後の段落は
長さ0、1、および2の場合です。(1)長さは0です。 、最も完璧な状況、長さ3のm個の小さなロープに分割する
(2)長さは1で、1を掛けた数はそれ自体であり、大きくなることはないので、前の段落で1と3を組み合わせた方がよいでしょう。 、得られる積が最大になるように
(3)長さは2で、これ以上除算することはできず、乗算するだけです。

注:これは主に貪欲な考えであり、毎回局所的な最適解を探します。
dpも書ける気がしますが、後で追加します

コード:

public class jianzhi_Offer_14_1 {
    
    
    public int cuttingRope(int n) {
    
    
        if(n == 2){
    
    
            return 1;
        }
        if(n == 3){
    
    
            return 2;
        }
        if (n == 4){
    
    
            return 4;
        }
        int ans = 1;
        int tmp;
        int num = n;
        while (num >= 3){
    
    
            if((num - 3) >= 3){
    
    
                ans *= 3;
                num -= 3;
            }
            else if((num - 3) == 1){
    
    
                ans *= 4;
                num -= 4;
                break;
            }
            else if((num - 3) == 2){
    
    
                ans *= 6;
                num -= 5;
                break;
            }
            else if((num - 3) == 0){
    
    
                ans *= 3;
                num -= 3;
                break;
            }

        }
        return ans;
    }

    public static void main(String[] args) {
    
    
        jianzhi_Offer_14_1 obj = new jianzhi_Offer_14_1();
        System.out.println(obj.cuttingRope(9));
    }
}

タイトル説明:

これが長さnのロープです。ロープを整数の長さのm個のセグメントに切断してください(mとnは整数、n> 1とm> 1)。各ロープの長さはk [0]、k [1です。 ] ... k [m-1]。k [0] k [1] …* k [m-1]の可能な最大の積は何ですか?たとえば、ロープの長さが8の場合、2、3、3の長さで3つに切断します。この時点で得られる最大の積は18です。
答えは1e9 + 7(1000000007)を法とする必要があります。計算の初期結果が1000000008の場合は、1を返します。

例1:
入力:2
出力:1
説明:2 = 1 + 1、1×1 = 1

例2:
入力:10
出力:36
説明:10 = 3 + 3 + 4、3×3×4 = 36

ヒント:
2 <= n <= 1000

出典:LeetCode
リンク:https ://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof
著作権はLeetCodeが所有しています商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。

問題解決のアイデア:

この質問と前者の違いは、nの値の範囲が大きくなることです。つまり、最終的に得られる答えは、intが耐えられる最大制限を超えます。このとき、剰余の分布を使用できます:
(a * b)%m =((a%m)*(b%m))%m
+循環剰余を使用して、問題を解決します。(中間乗算中に制限を超える可能性があるため、結果の残りを取得するには乗算する必要があります)

コード:

public class jianzhi_Offer_14_2 {
    
    
    public int cuttingRope(int n) {
    
    
        int modnum = 1000000007;
        if(n == 2){
    
    
            return 1;
        }
        if(n == 3){
    
    
            return 2;
        }
        if (n == 4){
    
    
            return 4;
        }
        //注意这里要使用long
        long ans = 1;
        int tmp;
        int num = n;
        while (num >= 3){
    
    
            ans = ans % modnum;
            if((num - 3) >= 3){
    
    
                ans = (ans * 3) % modnum;
                num -= 3;
            }
            else if((num - 3) == 1){
    
    
                ans = (ans * 4) % modnum;
                num -= 4;
                break;
            }
            else if((num - 3) == 2){
    
    
                ans = (ans * 6) % modnum;
                num -= 5;
                break;
            }
            else if((num - 3) == 0){
    
    
                ans = (ans * 3) % modnum;
                num -= 3;
                break;
            }

        }
        if( ans == modnum + 1)
            return 1;
        return (int)ans;
    }

    public static void main(String[] args) {
    
    
        jianzhi_Offer_14_2 obj = new jianzhi_Offer_14_2();
        System.out.println(obj.cuttingRope(120));
    }
}

おすすめ

転載: blog.csdn.net/Puppet__/article/details/115076052