算法题解记录29+++全排列(百日筑基)

一、题目描述

题目难度:中等
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]


示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]


示例 3:

输入:nums = [1]
输出:[[1]]


提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同

二、解题准备

第一,题意

不解释

第二,基本操作

涉及到数组的遍历,List的增加,可能还有List的删除。

第三,基础原理

对于回溯算法,从大的方面讲,题解一般涉及递归(迭代解法过于复杂)。
从小的方面讲,可能会关系到将题目、解题过程转化为解空间树
这棵解空间树,一般都是满多叉树(可能会用剪枝算法,降低运行时间)
一般来说,这棵解空间树,有这样的特点:
它的叶子节点是真正的题解。
它的其它节点,可以理解为解题过程
因此,学会遍历多叉树,是解题的基础算法,链接如下:
多叉树遍历算法

三、解题思路

针对该题,我们先手动地解题。
对于数组【a,b,c】
它的排列有以下可能:

第一,如果先选择a,

那么,余下【b,c】进行选择。

紧接着1,如果选择b,余下c进行选择

答案1为【a,b,c】

紧接着1,如果选择c,余下b选择

答案2为【a,c,b】

第二,如果先选择b,

那么,余下【a,c】进行选择。

紧接着2,如果选择a,余下c,

答案3为【b,a,c】
其它同理
我们可以发现,这颗多叉树,从空节点开始,每一层都会减少一个节点,如下图:
全排列

问题1:这不是满多叉树

想必你也发现了,随着层次减少,上一层总比下一层多出一个节点。
这是因为,在全排列中,如果某个位置使用了a,那么,其它的位置就不能使用a。
根据全排列的性质,我们可以得到这么个规律(假设length是输入数组的长度):
第一层:有length个节点【忽略,根节点】
第二层:有length-1个节点
……
第length层:有1个节点。此时,这个节点是叶子节点。【也就是我们需要的答案

问题2:这棵多叉树难以遍历

这棵多叉树虽然结构鲜明,但明显是个刺头,难以下手。
假如,我们使用一个boolean数组,来标记哪个节点被访问,然后根据访问情况,进行遍历判断。
也许可行,不过我没写出来,主要问题出现在:

// 随机拿一个未访问的节点
// 使boolean数组为true
访问。
// 设置boolean数组为false

这几个步骤中,有2大问题:
第一,随机访问节点,很可能会访问到上一次的节点,这会造成答案重复
第二,我们不能确定,究竟要访问多少次。【如果用nums的长度为标准,我们会发现,下一层节点,又只有上一层-1个。】

四、解题难点分析

难点如上所示。(我的观点)
难点定义:在数据处理的过程中,数据结构在不断变化
最开始,有length个节点。
第二层,剩下length-1个。
……
到最后一层,只有1个了。
我们没法用统一的结构,处理这个问题。

A1思考:递归函数的解决结构

我们学习过二叉树的DFS深度优先遍历,以及斐波那契的递归函数。
其实可以发现,它有递归调用递归的过程。

// 斐波那契
return feibo(n-1) + feibo(n-2);

然而,这两个方案处理的数据结构,是一致的
虽然斐波那契每次往前回调2次,但是,至始至终,处理的数据量都是2。
二叉树同理,每次处理的都是左子、右子两个节点。
在本题的多叉树中,每次处理的节点在依次减少

B2解决方案:双层递归函数

我们定义函数A,它提供一个方案:
A处理数据量为len的数组,依次从数组中拿出一个数,然后将此数移出数组,递归调用A函数,处理len-1的数组。
也就是说,A处理的对象是固定的
只处理数据量为len的数组,其它的情况,交给它的子递归函数。
并且,A处理的结构,每次会按要求减少,直到符合叶子节点,然后返回答案。
代码在下方,在此仅解释。

C3难点:确定参数

A的参数比较难以确定,这属于是回溯法的特点之一。
我在此介绍一种思路:
3个关键词:结果集答案集输入集
结果集:求解过程中的临时变量,到达叶子节点时,就是一个答案。
答案集:存储所有答案的全局或局部变量。
输入集:变化的数据结构。
另外的参数,需要看题目情况,动态地变化

D4难点:变化的输入集

由上可知,输入集在不断变化。
如果现在输入集为【a,b,c】
在选择后,剩下【b,c】
如果采用数组的结构,每次新生成一个数组,然后把【b,c】存储到数组,接着再递归调用。
可以发现,这会占用比较大的内存空间,而且数组复制的时间复杂度也不小。
因此,我们可以采用List链表,每次添加一个数,或者删除一个数,这样使用的内存空间会大大减少。

五、代码

class Solution {
    public List<List<Integer>> permute(int[] nums) {
    		// 答案集
            List<List<Integer>> res = new ArrayList<List<Integer>>();
    
    		// 输入集
            List<Integer> damn = new ArrayList<>();

			// 将数组转化为List,节省内存
            for(int i:nums){
                damn.add(i);
            }

            dfs_n(new ArrayList<>(), res, damn);
    
            return res;
        }
    
    	// data是结果集,临时答案
        private void dfs_n(List<Integer> data, List<List<Integer>> res, 
                List<Integer> damn){
            // size为0,就是叶子节点的下一层,该返回了
            if(damn.size() == 0){
                res.add(new ArrayList<>(data));
                return;
            }
    
    		// 每次访问输入集的长度
            for(int i=0; i<damn.size(); i++){
            	// tem仍要用于回溯,所以用个tem存储
                int tem = damn.get(i);
                // 结果集添加,输入集移除
                data.add(tem);
                damn.remove(i);

				// 调用子递归函数
                dfs_n(data, res, damn);
        
        		// 结果集移除,输入集恢复
                data.remove(data.size()-1);
                damn.add(i, tem);
            }
        }
}

六、结语

以上内容即我想分享的关于力扣热题29的一些知识。
我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript常见面试题(二)

文章目录 1.new操作符的实现原理2.map和Object的区别3.JavaScript脚本延迟加载的方式有哪些&#xff1f;4.JavaScript 类数组对象的定义&#xff1f;&#xff08;伪数组&#xff09;5. 数组有哪些原生方法&#xff1f;6.为什么函数的 arguments 参数是类数组而不是数组&#xf…

成都跃享未来教育咨询解锁新篇章

在快节奏的现代社会中&#xff0c;每个人都在追求着属于自己的非凡人生。而成都跃享未来教育咨询&#xff0c;正是那个能够智慧引领你走向成功、成就非凡人生的灯塔。 跃享未来教育咨询&#xff0c;位于历史悠久的文化名城成都&#xff0c;这里不仅有丰富的文化底蕴&#xff0c…

【C++进阶学习】第二弹——继承(下)——挖掘继承深处的奥秘

继承&#xff08;上&#xff09;&#xff1a;【C进阶学习】第一弹——继承&#xff08;上&#xff09;——探索代码复用的乐趣-CSDN博客 前言&#xff1a; 在前面我们已经讲了继承的基础知识&#xff0c;让大家了解了一下继承是什么&#xff0c;但那些都不是重点&#xff0c;今…

企业社会责任认证:提升品牌价值的关键

社会责任认证&#xff08;Social Responsibility Certification&#xff09;是现代企业在经营过程中主动履行社会责任、尊重人权、保护环境等方面所获得的认证。这不仅是企业管理的要求&#xff0c;更是企业赢得社会信任和支持的关键。 社会责任认证是企业在经营过程中&#xf…

nvm 报错https://npm.taobao.org/mirrors/node/index.json 淘宝镜像更换

文章目录 一、问题背景二、解决问题1. 获取配置文件的位置2. 修改配置文件中的镜像源配置3. 修改 npm 镜像源 一、问题背景 使用nvm的时候报错: Could not retrieve https://npm.taobao.org/mirrors/node/index.json. 由于淘宝的镜像域名更换&#xff0c;npm.taobao.org 域名…

基于WPF技术的换热站智能监控系统15--实时读取PLC数据

1、创建PLC实时数据 1、添加数据块 2、创建6个变量 用来表示水泵1和水泵2的参数&#xff0c;可以根据现场实际情况添加更多的变量参数 3、设置块属性并编译 4、下载该程序到PLC中 5、添加监控表 2、读取设备数据 S7协议下的tcp直接通讯&#xff0c;配置简单&#xff0c;一般P…

浏览器必装插件推荐:最新版Simple Allow Copy,解除网页复制限制!

经常在网上找资料的朋友&#xff0c;尤其是学生党&#xff0c;总会遇到一个问题&#xff1a;很多资料网站的文字是禁止复制的。于是大家通常会使用各种文字识别软件来图文转换&#xff0c;或者直接手打。 今天这款小工具&#xff0c;可以轻松复制各种氪金网站上的任何文字&…

李沐:用随机梯度下降来优化人生!

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 今天我们来聊聊达叔 6 大核心算法之 —— 优化 算法。吴恩达&#xff1a;机器学习的六个核心算法&#xff01; 梯度下降优化算法是机器…

【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 ​ 目录 一、问题描述 二、解题思路 方法一&#xff1a;数学公式推导法 方法…

Kaggle比赛:成人人口收入分类

拿到数据首先查看数据信息和描述 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 加载数据&#xff08;保留原路径&#xff0c;但在实际应用中建议使用相对路径或环境变量&#xff09; data pd.read_csv(r"C:\Users\11794\Desk…

超高清图像生成新SOTA!清华唐杰教授团队提出Inf-DiT:生成4096图像比UNet节省5倍内存。

清华大学唐杰教授团队最近在生成超高清图像方面的新工作&#xff1a;Inf-DiT&#xff0c;通过提出一种单向块注意力机制&#xff0c;能够在推理过程中自适应调整内存开销并处理全局依赖关系。基于此模块&#xff0c;该模型采用了 DiT 结构进行上采样&#xff0c;并开发了一种能…

持续学习的综述: 理论、方法与应用

摘要 为了应对现实世界的动态&#xff0c;智能系统需要在其整个生命周期中增量地获取、更新、积累和利用知识。这种能力被称为持续学习&#xff0c;为人工智能系统自适应发展提供了基础。从一般意义上讲&#xff0c;持续学习明显受到灾难性遗忘的限制&#xff0c;在这种情况下…

白酒:茅台镇白酒的酒厂社会责任与可持续发展

云仓酒庄豪迈白酒&#xff0c;作为茅台镇的品牌&#xff0c;不仅在产品品质和口感方面有着卓着的表现&#xff0c;在酒厂社会责任和可持续发展方面也做出了积极的探索和实践。 首先&#xff0c;云仓酒庄豪迈白酒注重环境保护和资源利用。酒厂在生产过程中严格控制能源消耗和排放…

使用 Nstbrowser 管理多个帐户 - 2024 年最佳反检测浏览器

每个人一定都看过那些房间里全是窃听器的老间谍电影&#xff0c;对吧&#xff1f;现在这些电影可能看起来有点好笑&#xff0c;但互联网并没有好到哪里去&#xff01; 事实上&#xff0c;每个你打开的页面在你浏览时都在被监控&#xff01;此外&#xff0c;当你管理多个账户时…

基于ChatGPT-4o自然科学研究全流程实践技术应用

自然科学研究遵循严谨的科学方法论&#xff0c;包括文献调研、问题综述、试验设计、提出假设、数据清洗、统计诊断、大数据分析、经典统计模型&#xff08;回归模型、混合效应模型、结构方程模型、Meta分析模型&#xff09;、参数优化、机器/深度学习、大尺度模型构建与模拟、论…

【AI开发】CRAG、Self-RAG、Adaptive-RAG

先放一张基础RAG的流程图 https://blog.langchain.dev/agentic-rag-with-langgraph/ 再放一个CRAG和self-RAG的LangChain官方博客 Corrective RAG(CRAG) 首先需要知道的是CRAG的特色发生在retrieval阶段的最后开始&#xff0c;即当我们获得到了近似的document&#xff08;或者…

【proteus仿真】基于51单片机的电压检测系统

【proteus仿真】基于51单片机的电压检测系统 资料下载地址&#xff1a;关注公众号 小邵爱电子 获取 1.前言 使用51单片机和ADC模块设计一个数字电压表&#xff0c;将模拟信号0~5V之间的电压转换为数字量信号&#xff0c;并通过LED实时显示电压数据 、 2.仿真原理图 3.硬件…

简单几步把完整的Windows塞进U盘,小白都能看懂

前言 小白之前写过相似的文章&#xff0c;但教程是通过WinPE操作实现的。 把Windows系统装进U盘&#xff0c;从此到哪都有属于你自己的电脑系统 有些小伙伴反馈教程写得很复杂&#xff0c;简直生涩难懂。 为啥要写得这么复杂呢&#xff1f;小白是想让小伙伴们多了解一些不同…

为什么MOSFET是双向导通的

MOSFET 的电压控制机理是利用栅极电压的 大小改变感应电场生成的导电沟道的厚度&#xff08;感生电荷的多少&#xff09;&#xff0c;来控制漏极电流 Id 的。从图1&#xff08;b&#xff09;中可 以看出&#xff0c;当栅极电压 V gs小于开启电压 V th时&#xff0c;无论 V ds的…

Android系统上Bootchart的使用

Android系统的启动细节分析&#xff0c;可以用工具bootchart来进行 一、Bootchart简介 官网地址&#xff1a;https://www.bootchart.org/ Google推荐bootchart作为开机优化的首选工具&#xff1a;https://source.android.com/devices/tech/perf/boot-times#bootchart bootc…