1. 括号生成
2. 组合总和
3. 字符串的全排列(带重复)
1. 括号生成
输入:n = 3
输出:[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
---------------------------------------------------------
class Solution {
List<String> list;
public List<String> generateParenthesis(int n) {
list = new ArrayList<>();
if(n <= 0) return list;
dfs("",0,0,n);
return list;
}
//left表示已经用了多少(,right表示已经用了多少)
public void dfs(String string, int left, int right, int n){
if(left == n && right == n){ //左右括号都用完,添加
list.add(string);
return;
}
if(left > n || right >n) return; //剪枝,左括号或者右括号超标了
if(right > left) return; //右>左,比如 (())),显然不可以,剪枝
else if(left == right){
dfs(string+"(" ,left+1, right, n); //相等时候,只能+(
}
else{
dfs(string+"(" ,left+1, right, n); 其余情况,两个都要试
dfs(string+")" ,left, right+1, n);
}
}
}
2. 组合总和
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
-------------------------------------------------------------------
class Solution {
List<List<Integer>> ans;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
ans = new ArrayList<>();
if(candidates.length ==0) return ans;
List<Integer> list = new ArrayList<>();
Arrays.sort(candidates);
dfs(list, candidates, 0, target, 0);
return ans;
}
//sum表示目前的总和
//start用来记录index防止重复,比如[2,3,4],target=5那么每次找完2开头的之后,下次只能从3开始找,不然会出现[2,3],[3,2]的重复情况
public void dfs(List<Integer> list, int[] candidates, int sum, int target, int start){
int length = candidates.length;
for(int i =start; i<length; i++){
if(sum + candidates[i] > target) break; //已经超过sum,剪枝
else if(sum + candidates[i] == target){ //正好相等,加入ans
list.add(candidates[i]);
ans.add(new ArrayList<Integer>(list));
list.remove(list.size()-1);
break;
}
else{
sum += candidates[i];
list.add(candidates[i]);
dfs(list, candidates, sum, target, i); //这里的start =i,下次从后面找,避免重复
list.remove(list.size()-1);
sum -= candidates[i]; //sum别忘了减
}
}
}
}
3. 字符串的全排列(带重复)
输入:s = "abcc"
输出:["abcc","acbc","accb","bacc","bcac","bcca","cbac","cbca","cabc","cacb","ccab","ccba"]
------------------------------------------------------------------
思路:回溯
class Solution {
List<String> list;
public String[] permutation(String s) {
int len = s.length();
if(len == 0) return new String[0];
if(len == 1) return new String[]{s};
list = new ArrayList<>();
backtrace(new StringBuilder(s), 0);
String[] ans = new String[list.size()];
for(int i =0; i< list.size(); i++){
ans[i] = list.get(i);
}
return ans;
}
public void backtrace(StringBuilder sb, int start){
int length = sb.length();
if(start +1 == length){
list.add(sb.toString());
return;
}
Set<Character> set = new HashSet<>();
//Set用来记录重复的
//比如start = 1,sb="abcdcdc"
//此时只有三种选择 ab开头,ac开头,ad开头
for(int i = start; i< length; i++){
char a = sb.charAt(i);
char b = sb.charAt(start);
if(set.contains(a)) continue;
else{
set.add(a);
}
sb.setCharAt(start,a);
sb.setCharAt(i,b);
backtrace(sb, start+1);
sb.setCharAt(start,b);
sb.setCharAt(i,a);
}
return;
}
}