【力扣一刷】代码随想录day29(回溯算法part5:491.递增子序列、46.全排列、47.全排列 II)

目录

【491.递增子序列】中等题

【46.全排列】中等题

【47.全排列 II】中等题


【491.递增子序列】中等题

思路:

1、处理当前节点

  • 如果到当前节点的路径长度为1或者为0,直接遍历访问子节点即可
  • 如果到当前节点的路径长度大于/等于2,则判断是否递增
    • 如果递增,则记录路径
    • 如果不是递增,则不记录路径,不访问子节点,直接返回

2、遍历子节点

  • 在for循环遍历前,定义Set对象,用于记录当前层遍历过的子节点(注意:不能定义为全局变量,因为递归的时候会加入其它层的节点)。
  • 在for循环遍历时,如果当前层前面出现过相同值的子节点,就不遍历该子节点,跳过。

难点:需要【判断子序列是否递增】和【考虑如何去重】

相似题目:【90.子集II】,但90题可以排序,通过与前一个子节点比较即可去重,而491题的结果与数组的元素顺序有关,不能排序,否则结果必错,所以需要使用额外的空间记录访问过的子节点。

class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> findSubsequences(int[] nums) {backtracking(nums, 0);return res;}public void backtracking(int[] nums, int start){// 如果到当前节点的路径长度大于/等于2,则判断是否递增(路径长度为1或者为0,直接遍历访问子节点即可)if (path.size() >= 2){// 如果递增,则记录路径if (path.get(path.size() - 1) >= path.get(path.size() - 2)) res.add(new ArrayList(path));// 如果不是递增,则不记录路径,不访问子节点,直接返回else return;}// 用于记录当前层遍历过的子节点(注意:不能定义为全局变量,因为递归的时候会加入其它层的节点)Set<Integer> set = new HashSet<>();for (int i = start; i < nums.length; i++){// 如果当前层前面出现过,就不遍历该子节点,跳过if (!set.isEmpty() && set.contains(nums[i])) continue; set.add(nums[i]);path.add(nums[i]);backtracking(nums, i + 1);path.remove(path.size() - 1);}}
}


【46.全排列】中等题

思路:

在遍历子节点的时候,先判断路径中是否已经包含想遍历的子节点,如果包含就不再遍历该子节点。

反思:

一开始自己实现的时候,使用了额外的Set对象记录访问过的节点,但是其实没有必要,因为额外Set对象做的事情和路径path变量做的事情一样,直接用path变量判断即可。

class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> permute(int[] nums) {backtracking(nums);return res;}public void backtracking(int[] nums){// 终止条件(如果路径长度和数组长度一样,证明已经排列完毕,将路径记录到res中)if (path.size() == nums.length) {res.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);path.remove(path.size() - 1);}}
}


【47.全排列 II】中等题

思路:和【46.全排列】的区别在于,数组中的元素是可以重复的。

  • 考虑树的纵向递归:要保证每个重复的元素都能用上,需要使用used数组记录元素的使用情况,而不能用简单的contains(存在重复元素,直接使用contains不合理)。
  • 考虑树的横向遍历:如果当前子节点前面遍历过,则得跳过当前子节点,因此需要用额外的Set对象记录当前层遍历过的子节点。
class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> permuteUnique(int[] nums) {boolean[] used = new boolean[nums.length]; // 默认初始化值为falsebacktracking(nums, used);return res;}public void backtracking(int[] nums, boolean[] used){// 长度一样则完成排列,记录结果并返回if (path.size() == nums.length){res.add(new ArrayList(path));return;}Set<Integer> set = new HashSet<>(); // 用于记录当前层遍历过的子节点for(int i = 0; i < nums.length; i++){if (used[i] == true) continue; // 如果上层已经用过了该元素,则跳过// 这里没有排序后直接和上一个元素比较,是因为上一个元素可能不是同一层的子节点if (set.contains(nums[i])) continue;  set.add(nums[i]); // 记录当前层遍历过的子节点used[i] = true;path.add(nums[i]);backtracking(nums, used);used[i] = false;path.remove(path.size() - 1);}}
}

优化:不使用额外的空间记录当前层遍历过的子节点

  • 问题:如果直接将nums先排序,再在递归for循环的时候,直接判断当前子节点是否与上一个子节点相同,这时无法保证上一个节点是当前层遍历过的子节点还是上层遍历过的节点。
  • 方案:需要在判断时,确保上个位置的元素是当前层的子节点,才能跳过。如果当前子节点和上个位置元素的值相同,且上个位置的元素未出现在路径中(即上个位置的元素也是当前层已遍历过的子节点),则跳过。
class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> permuteUnique(int[] nums) {Arrays.sort(nums);boolean[] used = new boolean[nums.length]; // 默认初始化值为falsebacktracking(nums, used);return res;}public void backtracking(int[] nums, boolean[] used){// 长度一样则完成排列,记录结果并返回if (path.size() == nums.length){res.add(new ArrayList(path));return;}for(int i = 0; i < nums.length; i++){if (used[i] == true) continue; // 如果上层已经用过了该元素,则跳过// 如果和上个位置元素的值相同,且上个位置的元素未出现在路径中(即上个位置的元素也是当前层已遍历过的子节点),则跳过if (i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue;used[i] = true;path.add(nums[i]);backtracking(nums, used);used[i] = false;path.remove(path.size() - 1);}}
}

总结:更加建议只使用used数组,而不用Set对象。

  • 原因1:不需要使用额外的空间
  • 原因2:不排序的去重有时候不一定完全能去重,存在风险,例如:例子。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/590062.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WebSocket】快速入门 springboot中使用

WebSocket 介绍 WebSocket缺点&#xff1a; 服务器长期维护长连接需要一定的成本 各个浏览器支持程度不一 WebSocket 是长连接&#xff0c;受网络限制比较大&#xff0c;需要处理好重连 结论&#xff1a; WebSocket并不能完全取代HTTP&#xff0c;它只适合在特定的场景下使用…

C++ 2024-4-2 作业

1.模板类实现顺序栈 #include <iostream> #define MAX 8 using namespace std; template<typename T> class stack {T data[MAX];int top; public:stack():top(-1){}bool empty_stack();bool full_stack();void push_stack(T data);void pop_stack();void show();…

Phpstorm配置Xdebug

步骤 1、先去官网找到对应的php xdebug的版本 2、配置phpstorm断点调试 网址&#xff1a;https://xdebug.org/ 查看php对应的xdebug版本&#xff1a;Xdebug: Support — Tailored Installation Instructions 1.1查看对应php xdebug版本 全选&#xff0c;复制到目标网址 我…

Flutter中setState函数的使用注意事项

文章目录 Flutter中setState函数的使用注意事项只能在具有State对象的类中使用不要在build方法中使用将状态更新逻辑放在setState方法内部避免频繁调用使用回调函数更新状态 Flutter中setState函数的使用注意事项 setState()函数是Flutter中非常重要的一个函数&#xff0c;它用…

antd/x6-graph——实现流程图绘制功能——技能提升

效果图&#xff1a; 解决步骤1&#xff1a;安装"antv/x6": "^1.35.0" npm install antv/x61.35.0安装指定版本的antv/x6插件 解决步骤2&#xff1a;配置tools文件 在assets/js中新增一个graphTools.js文件 内容如下&#xff1a; /* antv x6图谱相关…

基于深度学习的吸烟检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要&#xff1a;本文深入研究了基于YOLOv8/v7/v6/v5等深度学习模型的吸烟行为检测系统&#xff0c;核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;进行性能指标对比&#xff1b;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码&#xff0c;及…

目标跟踪——行人车辆数据集

一、重要性及意义 首先&#xff0c;目标跟踪对于个人和组织的目标实现至关重要。无论是个人职业发展、企业业务增长还是政府的社会发展&#xff0c;目标跟踪都能够帮助我们明确目标&#xff0c;并将其分解为可行的步骤和时间表。这有助于我们保持动力和专注&#xff0c;提高效…

WPF文本框TextEdit不以科学计数法显示

WPF文本框TextEdit不以科学计数法显示 一个float或者double类型的数值&#xff0c;如果小数点后0的个数≥4&#xff0c;在界面上就会自动以科学计数法显示&#xff0c; 比如&#xff1a;0.00003会显示成这样 但是很多时候我并不希望它这样显示&#xff0c;因为这样不方便编辑…

js手持小风扇

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 先编写动画&#xff0c;让风扇先转起来。使用 js 控制动画的持续时间。监听按钮的点击事件&#xff0c;在事件中修改元素的animation-duration属性。 3. 代码实现 <!DOCTYPE html> <html lang…

[计算机效率] 格式转换工具:格式工厂

3.14 格式转换工具&#xff1a;格式工厂 格式工厂是一款功能强大的多媒体格式转换软件&#xff0c;可以实现音频、视频、图片等多种格式的转换。它支持几乎所有类型的多媒体格式&#xff0c;包括视频、音频、图片、字幕等&#xff0c;可以轻松实现格式之间的转换&#xff0c;并…

Python基础之pandas:字符串操作与透视表

文章目录 一、字符串操作备注&#xff1a;如果想要全部行都能输出&#xff0c;可输入如下代码 1、字符检索2、字符转换3、字符类型判断4、字符调整5、字符对齐与填充6、字符检索7、字符切割8、字符整理 二、透视表1、pd.pivot_table2、多级透视表 一、字符串操作 备注&#xf…

Flask Python:数据库多条件查询,flask中模型关联

前言 在上一篇Flask Python:模糊查询filter和filter_by&#xff0c;数据库多条件查询中&#xff0c;已经分享了几种常用的数据库操作&#xff0c;这次就来看看模型的关联关系是怎么定义的&#xff0c;先说基础的关联哈。在分享之前&#xff0c;先分享官方文档,点击查看 从文档…