491.递增子序列
和求子集不同 求递增子序列就需要注意去重逻辑和求组合的区别 同时判断上一个记录的元素是否大于当前元素 并且要记录当前元素是否使用过(用了hashset)
Java代码:
class Solution{
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums){
backtracking(nums, 0);
return result;
}
public void backtracking(int[] nums, int startindex){
if(path.size() > 1){
result.add(new ArrayList<>(path));
}
HashSet<Integer> hs = new HashSet<>();
for(int i = startindex; i < nums.length; i++){
if(!path.isEmpty() && path.get(path.size() - 1) > nums[i] || hs.contains(nums[i])){
//如果当前路径不为空,并且最后一个元素大于当前元素,
// 或者HashSet中已经包含了当前元素
// 则跳过当前元素,不将其添加到路径中。
continue;
}
hs.add(nums[i]);//将当前元素添加到HashSet中,标记为已访问。
path.add(nums[i]);//将当前元素添加到路径path中
backtracking(nums, i + 1);
//递归调用backTracking方法,处理下一个元素,
//但是从i + 1开始,因为当前元素已经被考虑过。
path.remove(path.size() - 1);
//:在回溯时,从路径path中移除最后一个元素,以便尝试下一个元素。
}
}
}
46.全排列
首先就是在数学角度上想 组合和排列本身就不同 虽然有公式转换 但是本质不一样 排列是有序的 组合是无序的(1 2 3 的子集有8个 但是排列有6个 无序和有序不同)
在排列问题里不需要用startindex 因为排列问题中的递归里元素可以重复
Java代码:
class Solution{
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> permute(int[] nums){
if(nums.length == 0) return result;
backtracking(nums, path);
return result;
}
public void backtracking(int[] nums, LinkedList<Integer> path){
if(path.size() == nums.length){
result.add(new ArrayList<>(path));
}
for(int i = 0; i < nums.length; i++){
//如果path里已经有这个元素 就把当前元素跳过
if(path.contains(nums[i])) continue;
path.add(nums[i]);
backtracking(nums, path);
path.removeLast();
}
}
}
47.全排列 II
数组里有重复元素 所以要在递归过程里去重 但是保证结果 要注意树层和树枝的区别 这题只能用used记录当前元素是否使用过是较好的
Java代码:
class Solution {
List<List<Integer>> ans = 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);
backtracking(nums,used);
return ans;
}
private void backtracking(int[] nums, boolean[] used){
if(path.size() == nums.length){
ans.add(new ArrayList<>(path));
return;
}for(int i = 0; i < nums.length; i++){
//used[i - 1] == true 说明同一树枝nums[i - 1]使用过
//used[i - 1] == false 说明同一树层nums[i - 1]使用过
//如果同一树层nums[i - 1]使用过则直接跳过
if(i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false){
continue;
}
//如果同一树枝nums[i]没使用过开始处理
if(used[i] == false){
used[i] = true;
//标记同一树枝nums[i]使用过 防止同一树枝重复使用
path.add(nums[i]);
backtracking(nums, used);
path.removeLast();//回溯 说明同一树层nums[i]使用过 防止重复使用树层
used[i] = false;
}
}
}
}
还有三道比较难的 但是最近在期末考试我一点没复习 还是去复习一下先 那三道n皇后我自己有点印象 其他两道没写过 没关系 今天也是需要刷算法和八股的一天 努力找工作
LeetCode递增子序列与全排列算法解析
315

被折叠的 条评论
为什么被折叠?



