題目描述:
給定一根長度為n的繩子,請把繩子剪成m段(m、n都是整數,n>1並且m>1),每段繩子的長度記為k[0],k[1],…,k[m]。請問k[0]* k[1] * … *k[m]可能的最大乘積是多少?
例如,當繩子的長度是8時,我們把它剪成長度分別為2、3、3的三段,此時得到的最大乘積是18。
分析:
1、求乙個問題的最優解;
2、整體的問題的最優解是依賴各個子問題的最優解;
3、把大問題分解成若干個小問題,這些小問題之間還有互相重疊的更小的子問題;
4、為避免子問題的重複計算,我們儲存子問題的最優解。從上往下分析問題,從下往上求解問題。
上面的幾個條件可以看出,屬於動態規劃問題。
動態規劃:
1、定義函式f(n)表示為把長度為n的繩子剪成若干段後各段長度乘積的最大值。
2、對於第一刀,我們有n-1種可能的選擇,可推導出f(n)=max;
3、很明顯這是乙個從上至下的遞迴,但是這個遞迴存在很多重複的計算,所以使用 至下而上的動態規劃,將子問題的最優解儲存。
4、注意繩子剪成ix(n-i)和(n-i)xi是相同的;
5、注意不符合切割條件的輸入n,以及輸入為2、3長度時的結果,因為題中規定m>1。
**如下:
/*
* 使用動態規劃的思想
*/public int fun(int
length)
products[i] = max;
}return products[length];
}
貪心演算法:
1、貪心演算法在對問題求解時,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解;
2、選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關;
3、題目貪心策略:當n>=5時,盡可能多地剪長度為3的繩子;當剩下的繩子長度為4時,把繩子剪成兩段長度為2的繩子。
**如下:
/*
* 使用貪婪法
*/public int fun(int
length)
int timesof2 = (length - timesof3 * 3) / 2;
return (int) (math.pow(3, timesof3) * math.pow(2, timesof2));
}
數學證明:
1、當n<5時,我們會發現,無論怎麼剪下,乘積product <= n,n為4時,product最大為2*2=4;
2、當n>=5時,可以證明2(n-2)>n並且3(n-3)>n。而且3(n-3)>=2(n-2)。所以我們應該盡可能地多剪長度為3的繩子段。
劍指offer第二版 面試題14(java)
面試題14 剪繩子 題目描述 給定一根長度為n的繩子,請把繩子剪成m段 m n都是整數,n 1並且m 1 每段繩子的長度記為k 0 k 1 k m 請問k 0 k 1 k m 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到的最大乘積是18。邊界 m ...
劍指offer第二版 面試題6(java)
面試題6 從尾到頭列印鍊錶 題目 輸入乙個鍊錶的頭結點,從尾到頭反過來列印出每個結點的值 鍊錶的結點定義如下 public class listnode 注意 面試中,如果打算修改輸入的資料,最好先問好是否資料是允許修改的 思路 1.遍歷順序從頭到尾,列印順序從尾到頭,第乙個結點最開始被訪問,但是最...
劍指offer第二版 面試題8 java
題目描述 給定乙個二叉樹和其中的乙個結點,請找出中序遍歷順序的下乙個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指標 分析 情況 一 有右子樹,這時只需要把其右孩子作為下乙個遍歷的 並不是要找的 節點,然後沿著該節點的左子樹 如果有的話 出發,直到遇到葉子節點,那麼該葉子節...