力扣第39題 組合總和 中等難度 卡了一天沒做出來
先看一眼題:
我的思路:比如[1,2,6],target=9
先找到大於等於9的數,沒有則找到陣列長度length
從length-1遍歷到0,
比如這裡:
從6開始遍歷,遍歷到最前面為止
···遍歷6的時候,遞迴的尋找一個3,使得3+6等於9
······遞迴時,target變為3
······先找到大於等於3的數,然後其下標-1
······比如這裡,從2開始遍歷,遍歷到最前面為止
······遍歷2的時候,遞迴的找到一個1,使得1+2等於3
·········遞迴時,target變為1
·········先找到大於等於1的數,然後其下標-1
·········下標為-1,退出遞迴
······此時將[6,2,1]加入結果佇列
······遍歷1的時候,將[6,1,1,1]加入結果佇列
······由於1前面沒有數,遞迴結束
···遍歷2的時候,遞迴找到一個7
······遞迴時,target變為7
······從下標0開始(值為1)遍歷,(過程省略),將[2,1,1,1,1,1,1,1]加入結果佇列,遞迴結束
···遍歷22=4的時候,遞迴的找到一個5
······從下標0開始(值為1)遍歷,(過程省略),將[2,2,1,1,1,1,1]加入結果佇列,遞迴結束
···遍歷23=6的時候,遞迴的找到一個3
······從下標0開始(值為1)遍歷,(過程省略),將[2,2,2,1,1,1]加入結果佇列,遞迴結束
···遍歷24=6的時候,遞迴的找到一個1
······從下標0開始(值為1)遍歷,(過程省略),將[2,2,2,2,1]加入結果佇列,遞迴結束
···由於25>9,故遍歷結束,遞迴結束
···遍歷1的時候,由於[1,1,1,1,1,1,1,1,1]滿足條件,將其加入結果佇列
···由於1前面沒有數,無法遞迴遍歷,因此遞迴結束
結束,返回結果佇列
思路是沒錯的,但是程式碼寫起來出問題了,大概知道哪裡出問題了,返回值沒設定好,錯誤程式碼如下:
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> resList = new ArrayList<>();
int index;
//首先找到距離target最近的較大值或者target本身,從它-1開始對陣列前面的元素進行遍歷
for (index = 0; index < candidates.length; index++) {
if (candidates[index] == target) {
List<Integer> list = new ArrayList<>();
list.add(target);
resList.add(list);
break;
} else if (candidates[index] > target) {
break;
}
}
for (int i = index - 1; i >= 0; i--) {
//index對應的元素可能是由i對應的數的n倍+tar(新的target的簡稱)決定的
for (int k = 1; k * candidates[i] <= target; k++) {
List<Integer> list = new ArrayList<>();
int old = k * candidates[i];
//先放入k個candidates[i]
for (int j = 0; j < k; j++) {
list.add(candidates[i]);
}
if (old == target) {
resList.add(list);
} else {
//尋找target-old
int r = find(candidates, target - old, list, i, resList);
//如果r==target-old,說明list裡面沒有-1
if (r == target - old) {
resList.add(list);
}
}
}
}
return resList;
}
//從arr[0,right)裡找一個新的target,使得新的target+當前數==target,返回值為新的target
//找不到則返回-1
public static int find(int[] arr, int target, List<Integer> list, int right, List<List<Integer>> resList) {
//首先找到距離target最近的較大值或者target本身,從它-1開始對陣列前面的元素進行遍歷
int index;
boolean firstT = false;
for (index = 0; index < right; index++) {
if (arr[index] == target) {
list.add(target);
resList.add(list);
firstT = true;
//注意:此時雖然找到了滿足的數,但是這個數也有可能是比它更小的多個陣列成
//這兩種情況都要加入resList
//但是也有可能不存在比它更小的多個陣列成,避免錯誤的返回-1,所以引入firstT
//因為list是指標,所以不能直接remove
list = new ArrayList<>(list);
list.remove((Integer) target);
break;
} else if (arr[index] > target) {
break;
}
}
for (int i = index - 1; i >= 0; i--) {
//index對應的元素可能是由i對應的數的n倍+tar(新的target的簡稱)決定的
for (int k = 1; k * arr[i] <= target; k++) {
int old = k * arr[i];
//先放入k個arr[i]
for (int j = 0; j < k; j++) {
list.add(arr[i]);
}
if (old == target) {
resList.add(list);
return target;
} else {
//尋找target-old
int r = find(arr, target - old, list, i, resList);
//如果r==target-old,說明list裡面沒有-1
if (r == target - old) {
resList.add(list);
return r;
} else if (r == -1) {
//移除list裡放入的那個數
for (int j = 0; j < k; j++) {
list.remove((Integer) arr[i]);
}
}
}
}
}
if (firstT)
return target;
return -1;
}
實在是不想改了,要改動感覺工程還蠻大的,關鍵是寫遞迴的這個思路沒理清,所以看答案了。
看了答案,我吐了。答案的思路就是我這個思路,而且這種思路有一個名字,叫做回溯。回溯確實是用遞迴實現的,但是傳入的引數和返回值一定要好好思考怎麼寫啊……
答案的程式碼就不放了,這個題馬克一下,回來再看。學一下怎麼用遞迴實現回溯。
相關文章
- 力扣第29題 中等難度 兩數相除力扣
- 【力扣】組合總和3(組合的去重)力扣
- LeetCode39. 組合總和LeetCode
- 【刷題1】LeetCode 39. 組合總和 java基礎LeetCodeJava
- 力扣1052. 愛生氣的書店老闆-C語言實現-中等難度力扣C語言
- LeetCode題目:39. 組合總和 解題思路及Java實現LeetCodeJava
- 【力扣】組合總數(另一種整數溢位)力扣
- LeetCode 39. 組合總和 40.組合總和II 131.分割回文串LeetCode
- 【10月打卡~Leetcode每日一題】18. 四數之和(難度:中等)LeetCode每日一題
- Day 26| 39. 組合總和 、 40.組合總和II 、 131.分割回文串
- 【1月打卡~Leetcode每日一題】86. 分隔連結串列(難度:中等)LeetCode每日一題
- 程式碼隨想錄演算法訓練營第23天 | 39.組合總和 40.組合總和Ⅱ 131.分割回文串演算法
- 39、組合總和 | 演算法(leetode,附思維導圖 + 全部解法)300題演算法
- 程式碼隨想錄演算法訓練營第27天 | 39. 組合總和 、 40.組合總和II 、 131.分割回文串演算法
- 【一天一大 lee】四數相加 II (難度:中等) - Day20201127
- 第 178 場力扣周賽 第二題力扣
- 【力扣】電話號碼的組合(回溯法)力扣
- 程式碼隨想錄演算法訓練營第26天 | 回溯02:39. 組合總和、40.組合總和II、131.分割回文串演算法
- 力扣1438. 絕對差不超過限制的最長連續子陣列-C語言實現-中等難度力扣陣列C語言
- 力扣題解力扣
- 力扣-697. 陣列的度力扣陣列
- 20201125:力扣第216場周賽(下)力扣
- 20201124:力扣第216場周賽(上)力扣
- 377. 組合總和 Ⅳ
- 程式碼隨想錄演算法訓練營,9月19日 | 39. 組合總和,40.組合總和II,131.分割回文串演算法
- 卡圖難題
- 力扣題之迴文數力扣
- 力扣刷題——3096.得到更多分數的最少關卡數目力扣
- 談談三消遊戲關卡的難度控制問題:元素難度評分機制遊戲
- LeetCode216.組合總和lllLeetCode
- LeetCode40.組合總和IILeetCode
- LeetCode-040-組合總和 IILeetCode
- leetcode:組合總和II(回溯java)LeetCodeJava
- 力扣---2020.7.30力扣
- 力扣---2020.9.27力扣
- 力扣---2020.9.29力扣
- 力扣---2020.9.28力扣
- 力扣---2020.9.3力扣