算法训练(leetcode)二刷第二十一天 | 491. 非递减子序列、*46. 全排列、*47. 全排列 II、D

刷题记录

  • [491. 非递减子序列](#491. 非递减子序列)
  • [*46. 全排列](#*46. 全排列)
  • [*47. 全排列 II](#*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 复制代码
// 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 复制代码
// 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题目地址

本题中出现了重复数据,因此去重是本题的重点。

借助之前组合问题中的去重方案,先排序,再对挨着的元素进行去重。

但排列问题每次都是从头开始检索,因此需要判断相同元素是否已使用不能用起始下标的方式。

应该查看当前元素是否已使用。这种查看分两种:

  1. 在当前层使用
  2. 在当前分支(递归)使用
  • 当前层 使用时,前一个元素的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 复制代码
// 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 复制代码
// java
相关推荐
铉铉这波能秀2 分钟前
LeetCode Hot100数据结构背景知识之列表(List)Python2026新版
数据结构·leetcode·list
重生之我是Java开发战士8 分钟前
【优选算法】模拟算法:替换所有的问号,提莫攻击,N字形变换,外观数列,数青蛙
算法
仟濹14 分钟前
算法打卡 day1 (2026-02-06 周四) | 算法: DFS | 1_卡码网98 可达路径 | 2_力扣797_所有可能的路径
算法·leetcode·深度优先
yang)14 分钟前
欠采样时的相位倒置问题
算法
南极企鹅17 分钟前
springBoot项目有几个端口
java·spring boot·后端
历程里程碑18 分钟前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
A尘埃20 分钟前
物流公司配送路径动态优化(Q-Learning算法)
算法
天若有情67321 分钟前
【自研实战】轻量级ASCII字符串加密算法:从设计到落地(防查岗神器版)
网络·c++·算法·安全·数据安全·加密
清风拂山岗 明月照大江23 分钟前
Redis笔记汇总
java·redis·缓存
xiaoxue..38 分钟前
合并两个升序链表 与 合并k个升序链表
java·javascript·数据结构·链表·面试