算法训练Day29|* 491.递增子序列* 46.全排列* 47.全排列 II

简介: 算法训练Day29|* 491.递增子序列* 46.全排列* 47.全排列 II

LeetCode:491.递增子序列

491. 递增子序列 - 力扣(LeetCode)


1.思路:

创建两个全局变量,一个path收集符合条件的结果,另一个result收集所有符合条件的结果。

当path.size>=2时,符合条件:数量大于1,即刻加入result结果集中。

HashSet临时集合存储所有遍历过的元素,调用hs.contains()方法用于同一递归深度的树层去重!!!

for循环横向遍历实现广度搜索。


2.代码实现:

 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>(); // 创建收集结果的结果集
 3    List<Integer> path = new ArrayList<>(); // 收集每个结果
 4    public List<List<Integer>> findSubsequences(int[] nums) {
 5        backtracking(nums, 0); // 回溯函数
 6        return result; // 返回结果集
 7    }
 8    public void backtracking(int[] nums, int startIndex) {
 9        if (path.size() > 1) { // 单个结果集的长度大于1时,即刻加入到结果集中
10            result.add(new ArrayList<>(path));
11        }
12        HashSet<Integer> hs = new HashSet<>(); // 临时的结合hs,用于树层去重
13        for (int i = startIndex; i < nums.length; i++) {
14            if (!path.isEmpty() && path.get(path.size() - 1) > nums[i] || hs.contains(nums[i])) { // 什么时候去重?树层元素相同时,①路径元素不为空且path中最后一个数值大于当前nums[i] ②同一深度的树层包含同个元素时去重
15                continue;
16            }
17            hs.add(nums[i]); // 收集所有遍历的元素
18            path.add(nums[i]); // 符合条件的元素加入路径中
19            backtracking(nums, i + 1); // 回溯函数继续深度遍历添加符合条件的元素
20            path.remove(path.size() - 1);  // 回溯:结束本层回溯函数,返回上一层继续
21        }
22    }
23}

3.复杂度分析:

时间复杂度:一个元素在回溯一层同时进行for循环和调用递归函数时间耗费为2倍,n层位2^n;n个元素则复杂度为O(n*2^n).

空间复杂度:栈堆空间开销,递归函数消耗栈,层数最大为N,此时时间复杂度为O(n).堆空间开销为集合O(n)。则整体为O(n).


LeetCode:46.全排列

46. 全排列 - 力扣(LeetCode)


1.思路:

回溯函数不用传入startIndex来限定位置了,直接循环遍历即可,当长度和数组长度相同时加入到结果集中。终止条件:直到path中出现相同元素结束本层循环,继续下一次循环。(终止条件为什么不能是path.size()>nums.length??)


2.代码实现:

 1//实现一:
 2class Solution {
 3    List<List<Integer>> result = new ArrayList<>();
 4    List<Integer> path = new ArrayList<>();
 5    public List<List<Integer>> permute(int[] nums) {
 6        backtracking(nums);
 7        return result;
 8    }
 9    public void backtracking(int[] nums) {
10        if (path.size() == nums.length) {
11            result.add(new ArrayList<>(path));
12        }
13        for (int i = 0; i < nums.length; i++) {
14            if (path.contains(nums[i])) {
15                continue;
16            }
17            path.add(nums[i]);
18            backtracking(nums);
19            path.remove(path.get(path.size() - 1));
20        }
21    }
22}

实现2

 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>();
 3    LinkedList<Integer> path = new LinkedList<>();
 4    public List<List<Integer>> permute(int[] nums) {
 5        // if (num)
 6        backtracking(nums, path);
 7        return result;
 8    }
 9    public void backtracking(int[] nums, LinkedList<Integer> path) {
10        if (path.size() == nums.length) {
11            result.add(new ArrayList<>(path));
12        }
13        for (int i = 0; i < nums.length; i++) {
14            if (path.contains(nums[i])) { // 终止条件
15                continue;
16            }
17            path.add(nums[i]);
18            backtracking(nums, path);
19            path.removeLast();
20        }
21    }
22}

3.复杂度分析:

时间复杂度:一次遍历为n,n次遍历为n^2.为什么代码随想录给的是O(n!).

空间复杂度:栈开销O(n).堆开销为O(n).

LeetCode:47.全排列 II

47. 全排列 II - 力扣(LeetCode)

1.思路:

2.代码实现:

 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>(); // 存储结果的结果集
 3    List<Integer> path = new ArrayList<>(); // 收集每个符合条件的结果
 4    public List<List<Integer>> permuteUnique(int[] nums) {
 5        boolean[] used = new boolean[nums.length]; // used[]做标记
 6        Arrays.fill(used, false); // 全部赋予false
 7        Arrays.sort(nums); // 排序,便于剪枝(优化搜索)
 8        backtracking(nums, used); // 回溯函数
 9        return result; // 返回结果集
10    }
11    public void backtracking(int[] nums, boolean[] used) {
12        if (path.size() == nums.length) { // 当临时收集的结果等于nums数组长度时,加入到结果集
13            result.add(new ArrayList<>(path)); 
14            return; // 返回上一层
15        }
16        // 横向遍历 
17        for (int i = 0; i < nums.length; i++) {
18            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { // 树层去重
19                continue;
20            }
21            if (used[i] == false) { // 没有遍历过 才进行加入操作
22                used[i] = true; // 置为true表明没有遍历过
23                path.add(nums[i]); // 加入到结果中
24                backtracking(nums, used); // 回溯函数,计息递归
25                path.remove(path.size() - 1); // 去重
26                used[i] = false; //从一下数开始,当前数置为false
27            }
28        }
29    }
30}

3.复杂度分析:

时间复杂度:O(n2^n).有疑问:代码随想录O(n!n).

空间复杂度:O(n).


相关文章
|
5月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
210 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
4月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
5月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
5月前
|
算法 Java C++
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
|
5月前
|
算法 C++
蓝桥 算法训练 共线(C++)
蓝桥 算法训练 共线(C++)
|
8月前
knn增强数据训练
【7月更文挑战第27天】
62 10
|
8月前
|
数据采集 编解码 人工智能
破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍
【7月更文挑战第19天】DeepMind的JEST算法革新AI训练,提升效率13倍,节能10倍。通过联合数据批次选择,预训练指导及多分辨率训练,优化资源利用,降低能耗。实验显示性能提升,达到SOTA水平,但实施需大量资源,依赖优质参考模型。[论文链接](https://arxiv.org/pdf/2406.17711)
110 10
|
8月前
knn增强数据训练
【7月更文挑战第28天】
83 2
|
8月前
|
人工智能 边缘计算 算法
破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍
【7月更文挑战第20天】DeepMind unveils Switch Transformer, revolutionizing AI energy consumption. This novel algorithm boosts training efficiency by 13x and slashes energy use by 10x compared to ChatGPT, marking a significant leap towards eco-friendly AI.
103 2
|
7月前
|
算法 搜索推荐
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较

热门文章

最新文章