該題給咱們一個array,要求咱們找到全部不重複的子集
java
輸入: nums = [1,2,3]
輸出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
複製代碼
這裏咱們運用backtracking算法,先sort array在此題中其實並沒有意義,創建一個backtrack方法,在方法中,先創建一個新的ArrayList,而後用for loop添加新的元素,用遞歸向更深處搜索,搜索完後刪除新添加的元素算法
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, int start){
list.add(new ArrayList<>(tempList));
for(int i = start; i < nums.length; i++){
tempList.add(nums[i]);
backtrack(list, tempList, nums, i+1);
tempList.remove(tempList.size()-1);
}
}
}
複製代碼
該題與78幾乎同樣,可是涉及到了重複問題,這裏咱們先將array sort,而後比較當前位與前一位,若是相同則跳過當前位。數組
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, int start){
list.add(new ArrayList<>(tempList));
for(int i = start; i < nums.length; i++){
if(i > start && nums[i] == nums[i-1]) continue;
tempList.add(nums[i]);
backtrack(list, tempList, nums, i + 1);
tempList.remove(tempList.size()-1);
}
}
}
複製代碼
給定兩個整數 n 和 k,返回 1 ... n 中全部可能的 k 個數的組合。bash
輸入: n = 4, k = 2
輸出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
複製代碼
仍然採用backracking,寫一個backtrack helper function,而後檢測是否size是k,若是是k則把該tempList加入result listoop
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> list = new ArrayList<>();
if(n == 0 || k == 0) return list;
backtrack(list, new ArrayList<>(), 0, n, k);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int start, int n, int k){
if(tempList.size() == k) list.add(new ArrayList<>(tempList));
for(int i=start; i<n; i++){
tempList.add(i+1);
backtrack(list, tempList, i+1, n, k);
tempList.remove(tempList.size()-1);
}
}
}
複製代碼
給定一個無重複元素的數組 candidates 和一個目標數 target ,找出 candidates 中全部可使數字和爲 target 的組合。spa
candidates 中的數字能夠無限制重複被選取。code
輸入: candidates = [2,3,5], target = 8,
所求解集爲:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
複製代碼
該題與以前的題目思路徹底相同,只不過斷定條件爲target當前與0的關係,若是等於0則直接添加,小於0則剪枝,大於0則繼續向下探索,難點在於,遞歸時的i爲0,由於每一個數字能夠取無限次遞歸
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), candidates, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] candidates, int target, int start){
if(target < 0) return;
else if(target == 0) list.add(new ArrayList<>(tempList));
else{
for(int i=start; i<candidates.length; i++){
tempList.add(candidates[i]);
backtrack(list, tempList,candidates, target-candidates[i], i);
tempList.remove(tempList.size()-1);
}
}
}
}
複製代碼
思路徹底相同,先sort而後斷定當前的數字與前一個數字是否相等,若是相等則跳過rem
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(candidates);
backtrack(list, new ArrayList<>(), candidates, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] candidates, int target, int start){
if(target < 0) return;
else if(target == 0) list.add(new ArrayList<>(tempList));
else{
for(int i=start; i<candidates.length; i++){
if(i > start && candidates[i] == candidates[i-1]) continue;
tempList.add(candidates[i]);
backtrack(list, tempList, candidates, target-candidates[i], i+1);
tempList.remove(tempList.size()-1);
}
}
}
}
複製代碼
找出全部相加之和爲 n 的 k 個數的組合。組合中只容許含有 1 - 9 的正整數,而且每種組合中不存在重複的數字get
77 題和 40 題的結合題,須要統計還剩餘的n,並且要斷定當前的tempList的size是否爲k,能夠直接用一個1-9的array也能夠直接用進for loop
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> list = new ArrayList<>();
if(n == 0 || k == 0) return list;
backtrack(list, new ArrayList<>(), n, k, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int n, int k, int start){
if(n == 0){
if(tempList.size() == k) list.add(new ArrayList<>(tempList));
else return;
}
else if(n < 0) return;
else{
for(int i = start; i < 9; i++){
tempList.add(i+1);
backtrack(list, tempList, n-i-1, k, i+1);
tempList.remove(tempList.size()-1);
}
}
}
}
複製代碼
這道題能夠用backtracking的作法,可是會超時,該用dp解法
dp[i] = 每個能到dp[i]的step的數量總和
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target+1];
dp[0] = 1;
for(int i = 0; i < dp.length; i++){
for(int num:nums){
dp[i] += dp[i-num];
}
}
return dp[target];
}
}
複製代碼
給定一個不重複的數組,返回全部的排列組合
輸入: [1,2,3]
輸出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
複製代碼
Main function 與以前全部題目相同,斷定條件爲是否長度爲nums.length,爲true則獲取了所有元素,在for loop中要斷定當前的tempList裏是否已經包含了當前元素,若是包含則跳過(剪枝)
class Solution {
public List<List<Integer>> permutations(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums){
if(tempList.size() == nums.length) list.add(new ArrayList<>(tempList ));
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i])) continue;
tempList.add(nums[i]);
backtrack(list, tempList, nums);
tempList.remove(tempList.size()-1);
}
}
}
複製代碼