刷题记录
- 491. 非递减子序列
- *46. 全排列
- *47. 全排列 II
- D
491. 非递减子序列
leetcode题目地址
题目提供的数据有重复,但结果集中不可有重复组合,且不允许排序,因此需要借助Set或额外的hash表进行标记当前层是否使用了相同元素。
时间复杂度: O ( n ∗ 2 n ) O(n*2^n) O(n∗2n)
空间复杂度: O ( n ) O(n) O(n)
// java
class Solution {private List<Integer> path = new LinkedList<>();// private Set<List<Integer>> result = new HashSet<>();private List<List<Integer>> result = new ArrayList<>();public void backtracking(int[] nums, int startIdx){if(path.size() > 1) {result.add(new ArrayList<>(path));}Map<Integer, Boolean> hash = new HashMap<>();for(int i=startIdx; i<nums.length; i++){if(hash.getOrDefault(nums[i], false)) continue;if(path.isEmpty() || nums[i] >= path.getLast()){path.add(nums[i]);hash.put(nums[i], true);backtracking(nums, i+1);path.removeLast();}}}public List<List<Integer>> findSubsequences(int[] nums) {backtracking(nums, 0);return result;// return new ArrayList<>(result);}
}
*46. 全排列
leetcode题目地址
全排列与组合问题的区别在于每次搜索都是从0开始,但需要标记哪些数据已使用。当路径长度等与数组长度时加入结果集。本题没有重复数据,因此不存在去重操作,直接回溯即可。
时间复杂度: O ( n ! ) O(n!) O(n!)
空间复杂度: O ( n ) O(n) O(n)
// java
class Solution {public List<Integer> path = new LinkedList<>();public List<List<Integer>> result = new ArrayList<>();public void backtracking(int[] nums, boolean[] used){if(path.size() == nums.length){result.add(new ArrayList<>(path));return;}for(int i=0; i<nums.length; i++){if(used[i]) continue;path.add(nums[i]);used[i] = true;backtracking(nums, used);path.removeLast();used[i] = false;}}public List<List<Integer>> permute(int[] nums) {boolean[] used = new boolean[nums.length];backtracking(nums, used);return result;}
}
*47. 全排列 II
leetcode题目地址
本题中出现了重复数据,因此去重是本题的重点。
借助之前组合问题中的去重方案,先排序,再对挨着的元素进行去重。
但排列问题每次都是从头开始检索,因此需要判断相同元素是否已使用不能用起始下标的方式。
应该查看当前元素是否已使用。这种查看分两种:
- 在当前层使用
- 在当前分支(递归)使用
- 在当前层使用时,前一个元素的used值应当是false,因为已经访问过经历了一次used[i] = true;和一次used[i] = false;也就是相同元素在当前层使用。
- 在当前分支使用时,前一个元素的used值应当是true,因为是在设置了used[i] = true;之后进入了递归backtracking(nums, used);也就是相同元素在当前分支使用。
时间复杂度: O ( n ! ∗ n ) O(n!*n) O(n!∗n)
空间复杂度: O ( n ) O(n) O(n)
// java
class Solution {private List<Integer> path = new LinkedList<>();private List<List<Integer>> result = new ArrayList<>();public void backtracking(int[] nums, boolean[] used){if(path.size() == nums.length) {result.add(new ArrayList<>(path));return;}for(int i=0; i<nums.length; i++){// 当前分支if(i>0 && nums[i] == nums[i-1] && !used[i-1]) continue;// 当前层// if(i>0 && nums[i] == nums[i-1] && used[i-1]) continue;if(used[i]) continue;path.add(nums[i]);used[i] = true;backtracking(nums, used);path.removeLast();used[i] = false;}}public List<List<Integer>> permuteUnique(int[] nums) {Arrays.sort(nums);boolean[] used = new boolean[nums.length];backtracking(nums, used);return result;}
}
D
leetcode题目地址
题解思路
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
// java