77. 組合
我的這個解法還算挺簡單易懂的,還是看註釋
class Solution {
List<List<Integer>> ans = new ArrayList(); //儲存最終結果集合
List<Integer> tmp = new ArrayList(); //記錄單次的path
public List<List<Integer>> combine(int n, int k) {
backTracking(n, k);
return ans;
}
public void backTracking(int n, int k){ //從1~n挑選k個陣列合的方法
if(n < k) return; //若k > n 顯然,不存在這樣的組合
if(k == 1){ //從n個數中挑選一個
for(int i = n; i > 0; i--){ //對於1~n任選一個新增到結果中即可
tmp.add(i);
ans.add(new ArrayList(tmp));
tmp.remove(tmp.size()-1); //回溯
}
return;
}
//這裡也可以新增剪枝,即n == k的時候,直接放入結果即可
//k > 1的情況,還可以分成兩種
//1. 選擇n,再從n-1中選擇k-1個數字
tmp.add(n);
backTracking(n-1, k-1);
tmp.remove(tmp.size()-1);
//2. 不選n,從n-1中選擇k個即可
backTracking(n-1, k);
}
}
216. 組合總和 III
與上一題的做法差不太多,但是剪枝的操作我考慮的並不完整。這裡使用
class Solution {
List<List<Integer>> ans = new ArrayList();
List<Integer> path = new ArrayList();
public List<List<Integer>> combinationSum3(int k, int n) {
backTracking(1, k, n);
return ans;
}
public void backTracking(int start, int k, int sum){ //start代表了現在可以取的第一個數字
// sum代表了還需要加多少才能符合條件
if(path.size() > k || sum < 0) return; //sum < 0 代表當前組合的和大於目標值了
if(path.size() == k) {
if(sum == 0) ans.add(new ArrayList(path));
return;
}
for(int i = start; i <= 9; i++){ //所有的回溯都可以抽象成樹結構(多叉樹)
//for迴圈相當於對每個子節點進行訪問,只有訪問到葉子節點才進行儲存結果,也就是遞迴的出口
path.add(i);
backTracking(i+1, k, sum-i);
path.remove(path.size()-1);
}
}
}
17. 電話號碼的字母組合
class Solution {
List<String> res = new ArrayList();
StringBuilder sb = new StringBuilder();
String[] map = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
if(digits.length() == 0) return res;
backTracking(digits, 0);
return res;
}
public void backTracking(String digits, int index){ //index代表當前要處理的數字在digits中的index
if(sb.length() == digits.length()) {
res.add(sb.toString());
return;
}
int digit = digits.charAt(index) - '0';
String s = map[digit];
for(char c: s.toCharArray()){
sb.append(c);
backTracking(digits, index+1);
sb.deleteCharAt(sb.length()-1);
}
}
}