題目:給定一個無重複元素的陣列 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。
說明:解集不能包含重複的組合。回溯演算法。
示例:
輸入:candidates = [2,3,5], target = 8,所求解集為:[ [2,2,2,2], [2,3,3], [3,5]]
我的思路: 該題目型別也是回溯演算法裡面的比較經典的題型,求陣列的組合。該題目已經說明了輸入數組裡面沒有重複數字,且可以無限制的被選取。那麼我們該怎麼解了? 從第一個數字開始,無限制的選取該數字,直到取得的總和 大於target, 那麼我們開始回退,嘗試取第二個數字。 回溯演算法本身就是暴力的窮舉,直到得到答案,當然,其中也可以加一些減枝,是演算法更優。
以下是我的答案:
解法一:
public static List<List<Integer>> combinationSum4(int[] candidates, int target) { List<List<Integer>> lists = new ArrayList<>(); back4(candidates, 0, target, new ArrayList<>(), lists); return lists; } public static void back4(int[] candidates, int cur, int target, List<Integer> pick, List<List<Integer>> res) { if (target == 0) { res.add(new ArrayList<>(pick)); return; } for (int i = cur; i < candidates.length; i++) { if (target >= candidates[i]) { pick.add(candidates[i]); //傳入當前索引下標,下次繼續從當前選起 back4(candidates, i, target - candidates[i], pick, res); pick.remove(pick.size() - 1); } } }
解法二:
每一個元素都有兩種選擇,選或者不選。
public static List<List<Integer>> combinationSum5(int[] candidates, int target) { List<List<Integer>> lists = new ArrayList<>(); back4(candidates, 0, target, new ArrayList<>(), lists); return lists; } public static void back5(int[] candidates, int cur, int target, List<Integer> pick, List<List<Integer>> res) { if (target == 0) { res.add(new ArrayList<>(pick)); return; } if(cur == candidates.length)return; //不選當前數字 back5(candidates, cur + 1, target, pick, res); //選當前數字 if (target >= candidates[cur]) { pick.add(candidates[cur]); back4(candidates, cur, target - candidates[cur], pick, res); pick.remove(pick.size() - 1); } }
最新評論