回溯法 主要要考虑三种情况:
如果是输出的是全排列,即元素顺序不一样,也属于不一样的结果:
设置循环: for (int i = 0; i < nums.length; i++) ,不需要记录当前下标,例如:idx+1或者idx 带入到下一轮循环dfs(nums, temp)
还需要设置visited数组来标记已遍历元素
如果输出的结果,元素顺序不一样,但属于一样的结果;但是每个元素能重复使用;
设置循环: for (int i = idx; i < nums.length; i++) ,需要记录当前下标,idx 带入到下一轮循环dfs(nums, temp)
不需要设置visited数组来标记已遍历元素
如果输出的结果,元素顺序不一样,但属于一样的结果;每个元素不能重复使用;
设置循环: for (int i = idx; i < nums.length; i++) ,需要记录当前下标,idx+1 带入到下一轮循环dfs(nums, temp)
不需要设置visited数组来标记已遍历元素
简单来说(上述总结):
一、是否包含重复元素:
如果是全排列(顺序不一样,结果不一样):需要排序+设置剪枝条件:if(i>index && candidates[i] == candidates[i-1]) continue; 没有重复元素则不用加。
如果不是全排列(顺序不一样,结果一样),需要排序+设置剪枝条件:if(i>0&& candidates[i] == candidates[i-1]) continue; 没有重复元素则不用加。
二、当前元素能否被重复选取:
- 如果是全排列(顺序不一样,结果不一样),设置循环: for (int i = 0; i < nums.length; i++) ,还需考虑当前元素能否被重复选取,若不能则设置visited数组来标记已遍历元素;若能则不需要。
- 如果不是全排列(顺序不一样,结果一样),设置循环: for (int i = idx; i < nums.length; i++) ,还需考虑当前元素是否能够重复选取:若不能则dx+1 带入到下一轮循环dfs(nums, temp);若能重复选取则记录当前下标,idx 带入到下一轮循环dfs(nums, temp);
总结循环条件里的i初始化:
class Solution {
List<List<Integer>> res;
List<Integer> path;
public List<List<Integer>> permute(int[] nums){
res = new ArrayList<>();
path = new ArrayList<>();
int[] visited = new int[nums.length];
dfs(nums, visited);
return res;
}
public void dfs(int[] nums, int[] visited) {
if(path.size() == nums.length){
res.add(new ArrayList(path));
return;
}
for(int i=0; i<nums.length; i++){
if(visited[i] == 1) continue;
path.add(nums[i]);
visited[i] = 1;
dfs(nums, visited);
visited[i] = 0;
path.remove(path.size()-1);
}
}
}
class Solution {
public String[] permutation(String s) {
List<String> res = new ArrayList<>();
StringBuilder sb = new StringBuilder();
char[] arr = s.toCharArray();
Arrays.sort(arr);
boolean[] used = new boolean[s.length()];
backtracking(0, sb, res, used, arr);
return res.toArray(new String[res.size()]); //?
}
private void backtracking(int level, StringBuilder sb, List<String> res, boolean[] used, char[] arr){
if(level == arr.length){
res.add(sb.toString());
return;
}
for(int i=0; i<arr.length; i++){
if(used[i]) continue;
//处理同层重复元素 剪枝
if(i>0 && arr[i]==arr[i-1] && !used[i-1]) continue;
sb.append(arr[i]);
used[i] = true;
backtracking(level+1, sb, res, used, arr);
sb.deleteCharAt(sb.length()-1);
used[i] = false;
}
}
}
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
public List<List<Integer>> permuteUnique(int[] nums) {
res = new LinkedList<>();
path = new LinkedList<>();
boolean[] visited = new boolean[nums.length];
Arrays.sort(nums);
dfs(nums, visited);
return res;
}
public void dfs(int[] nums, boolean[] visited){
if(path.size() == nums.length){
res.add(new LinkedList(path));
return;
}
for(int i=0; i<nums.length; i++){
if(i>0 && nums[i] == nums[i-1] && !visited[i-1]) continue;
if(visited[i]) continue;
path.add(nums[i]);
visited[i] = true;
dfs(nums,visited);
visited[i] = false;
path.removeLast();
}
}
}
class Solution {
LinkedList<List<Integer>> res;
LinkedList<Integer> path;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
res = new LinkedList<>();
path = new LinkedList<>();
Arrays.sort(candidates);
dfs(candidates, 0, target);
return res;
}
public void dfs(int[] candidates, int index, int target) {
if(target == 0) {
res.add(new LinkedList<>(path));
return;
}
for(int i=index; i<candidates.length; i++){
if(target-candidates[i] < 0) break;
path.add(candidates[i]);
dfs(candidates, i, target-candidates[i]);
path.removeLast();
}
}
}
class Solution {
LinkedList<Integer> path;
LinkedList<List<Integer>> res;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
path = new LinkedList<>();
res = new LinkedList<>();
Arrays.sort(candidates);
dfs(candidates, 0,target);
return res;
}
public void dfs(int[] candidates, int index, int target) {
if(target == 0){
res.add(new LinkedList(path));
return;
}
for(int i=index; i<candidates.length; i++){
if(target-candidates[i] < 0) break;
if(i>index && candidates[i] == candidates[i-1]) continue;
path.add(candidates[i]);
dfs(candidates,i+1,target-candidates[i]);
path.removeLast();
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums, 0, new ArrayList<>());
return res;
}
public void dfs(int[] nums, int idx, List<Integer> temp) {
res.add(new ArrayList<>(temp));
for (int i = idx; i < nums.length; i++) {
temp.add(nums[i]);
dfs(nums, i+1, temp);
temp.remove(temp.size() - 1);
}
}
}