注:此博客不再更新,所有最新文章將發表在個人獨立博客limengting.site。分享技術,記錄生活,歡迎大家關注
題目描述:
給你一根長度爲n的繩子,請把繩子剪成m段(m和n都是整數,n > 1,m > 1),每段繩子的長度記爲k[0],k[1],k[2]…k[m]。請問k[0] * k[1] * … * k[m]可能的最大乘積是多少?例如,當繩子的長度爲8時,我們把它分別剪成2,3,3的三段,此時乘積最大是18。
思路一:利用動態規劃,自下而上的循環,原理同斐波那契數列,時間複雜度O(n²),空間複雜度O(n)
public class CutThread {
public static int maxProductAfterCutting(int length) {
if (length < 1) return -1;
int[] res = new int[length + 1];
res[0] = 0;
res[1] = 1;
res[2] = 2;
res[3] = 3;
for (int i = 4; i <= length; i ++) {
int max = 0;
for (int j = 1; j <= i / 2; j ++) {
int tmp = res[j] * res[i - j];
if (tmp > max) max = tmp;
}
res[i] = max;
}
return res[length];
}
public static void main(String[] args) {
System.out.println(maxProductAfterCutting(15));
}
}
思路二,貪婪算法,儘可能剪長度爲3的繩子,如果最後的餘數是1,則將最後一個3和剩下的1拼成4不剪斷,時間複雜度O(1),空間複雜度O(1)
證明:當n >=5 時,有剪成2,3,4,5四個選擇,剪成2和4是等價的,因爲2 × 2 = 4,剪成5不如把5分成2 × 3 = 6,在2和3中易證3(n - 3) >= 2(n - 2) > n,故應該儘可能多地將繩子剪成長度爲3的段,但是如果n = 4,4 > 3 * 1,故保持4不剪。
import static java.lang.Math.pow;
public class CutThread {
public static int maxProductAfterCutting(int length) {
if (length < 1) return -1;
int timesOf3 = length / 3;
if (length % 3 == 2) return 2 * (int)pow(3, timesOf3);
if (length % 3 == 1) return 4 * (int)pow(3, timesOf3 - 1);
else return (int)pow(3,timesOf3);
}
public static void main(String[] args) {
System.out.println(maxProductAfterCutting(15));
}
}