本人在此声明,本人所使用的解题思路,大多来自于代码随想录。@代码随想录
一、全排列
1、力扣64:全排列
解题思路:根据代码随想录的回溯三部曲进行解题,具体思路我会写到代码注释中。
//创建
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
//全排列的话,需要一个布尔数组记录这个数字是否被选择过。
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length < 2){
return result;
}
used = new boolean[nums.length];
backing(nums);
return result;
}
public void backing(int[] nums){
//递归的终止条件
if (path.size() == nums.length){
result.add(new ArrayList<>(path));
}
//单层搜索的逻辑+回溯
for (int i = 0; i < nums.length; i++) {
if (used[i]){
continue;
}
used[i] = true;
path.add(nums[i]);
backing(nums);
//回溯
path.removeLast();
used[i] = false;
}
}
2、力扣47:全排列 II
解题思路:还是根据代码随想路的回溯三部曲进行解题,但是中间加了个去重的步骤,去重的话首先要做排序,然后有树层去重和树枝去重。
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
boolean[] used = new boolean[nums.length];
Arrays.fill(used,false);
Arrays.sort(nums);
backTrack(nums,used);
return result;
}
public void backTrack(int[] nums,boolean[] used){
if (path.size() == nums.length){
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
//这里就是去重的代码,首先used[i]==false就是树层的去重,false就是回溯回去的所以
//就是层级上的,true就是前一个元素还是被选中的,所以就是树枝上的去重,两个都是可以
//实现去重的
if (i>0 && nums[i] == nums[i-1] && used[i-1] == false){
continue;
}
if (used[i] == false){
used[i] = true;
path.add(nums[i]);
backTrack(nums,used);
path.removeLast();
used[i] = false;
}
}
}
二、组合问题
1、力扣77:组合
解题思路:根据代码随想录的回溯三部曲进行解题,具体思路我会写到代码注释中。
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(n,k,1);
return result;
}
public void dfs(int n,int k,int begin){
//结束条件就是遍历到的数组长度达到k
if(path.size() == k){
result.add(new ArrayList<>(path));
return;
}
//遍历,这里有一个剪枝的操作,当剩下的元素不足要求的长度就不往下遍历了
for(int i = begin;i<=n-(k-path.size())+1;i++ ){
path.add(i);
dfs(n,k,i+1);
path.removeLast();
}
}
}