491.递增子序列
题目链接:https://leetcode.com/problems/non-decreasing-subsequences
Given an integer array nums, return all the different possible non-decreasing subsequences of the given array with at least two elements. You may return the answer in any order.
Input: nums = [4,6,7,7]
Output: [[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
思路:
- 子集+去重+有序
- 一个元素不能重复使用,需要startindex
- 同一父节点下的同层上使用过的元素就不能再使用了,数层去重,但是不能用排序+used数组
- unordered set
- unordered_set uset; 是记录本层元素是否重复使用,新的一层uset都会重新定义(清空),所以要知道uset只负责本层!
unordered set标记遍历过的同层节点,每层都会重新定义
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;
}
private void backtracking(int[] nums, int startIndex){
if (path.size() >= 2){
result.add(new ArrayList<>(path));
}
HashSet<Integer> hs = new HashSet<>(); //每层重新
for (int i = startIndex; i < nums.length; i++) {
if (!path.isEmpty() && nums[i] < path.get(path.size()-1)
|| hs.contains(nums[i])) { // 递增+去重
continue;
}
path.add(nums[i]);
hs.add(nums[i]);
backtracking(nums, i+1);
path.remove(path.size()-1);
}
}
}
时间复杂度: O(n * 2^n)
空间复杂度: O(n)
46.全排列
题目链接:https://leetcode.com/problems/permutations/
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
思路:
- 排列是有序的, [1,2] 和 [2,1] 是两个排列
- 1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了,每次都要从头搜索
- used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次
used数组记录使用过的
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
boolean[] used = new boolean[nums.length];
backtracking(nums, used);
return result;
}
private 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] == true) {
continue;
}
path.add(nums[i]);
used[i] = true;
backtracking(nums, used);
used[i] = false;
path.remove(path.size()-1);
}
}
}
path contains判定使用过的元素
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
boolean[] used = new boolean[nums.length];
backtracking(nums, used);
return result;
}
private 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 (path.contains(nums[i])) {
continue;
}
path.add(nums[i]);
backtracking(nums, used);
path.remove(path.size()-1);
}
}
}
时间复杂度: O(n!)
空间复杂度: O(n)
47.全排列 II
题目链接:https://leetcode.com/problems/permutations-ii
Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.
Input: nums = [1,1,2]
Output:
[[1,1,2],
[1,2,1],
[2,1,1]]
思路:
- 给定一个包含重复数字的序列,返回所有不重复的全排列。
- 去重需要排序,对同一树层,前一位(也就是nums[i-1])如果使用过,那么就进行去重。
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
boolean[] used = new boolean[nums.length];
Arrays.sort(nums);
backtracking(nums, used);
return result;
}
private 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] == true) { // path里已经收录的元素,直接跳过
continue;
}
if (i>0 && nums[i] == nums[i-1] && used[i-1] == false) { // 数层去重
continue;
}
path.add(nums[i]);
used[i] = true;
backtracking(nums, used);
path.remove(path.size()-1);
used[i] = false;
}
}
}