代码随想录day28

news/2024/11/19 21:30:35/

46. 全排列

 思路:这道题首先是一个排列问题,排列问题是讲究顺序的,例如[1,2]和[2,1]是两个不一样的排列,这里的1我们会有重复使用到,但是,在每一个排列中,每一个元素只能使用一次。所以需要一个状态数组初始化为false *len(nums)来标记。当我们第一次使用的时候发现这个元素没有被用过就加入到path中,加入完了之后要把他的状态变为true,标识我们当前这个元素已经用过了。然后进行撤销,因为我们已经把这个排列加入了结果集中,收获到了结果,需要进行回溯 回到上一层,然后再次从头开始搜索,这里状态就又要成为false.

 回溯三部曲:

        递归参数:因为是排列问题,每个组合都会重复用到一个元素,就不需要startindex了,这里只需要一个index,我们最后调用的时候从0开始调用就行。所以参数是nums,index.

        终止条件:

当我们的收获到的path的长度已经和nums的长度一样了,说明我们完全遍历完了,也就是该收获的时候了,所以加入结果集然后return

        单层循环逻辑:if used[i]==false,那我们就加入到path中,开始递归  改变状态 然后回溯+撤销。

代码:

def permute(self, nums: List[int]) -> List[List[int]]:res = []track = []used = [False] * len(nums)def back_trace(nums,index):if len(track)==len(nums):#深度优先遍历时,返回列表是为空的res.append(track[:])return for i in range(len(nums)):'如果当前节点没有被访问过'if used[i]==False:'就加入到track中并且状态改为已访问'track.append(nums[i])used[i]=True'回溯'back_trace(nums,0)track.pop()used[i] = Falseelse:continueback_trace(nums,0)return res

47. 全排列 II

  和上一个题不一样的是,nums数组中出现了重复的元素,并且我们的输出结果中,也有重复的元素,但是要求返回不重复的排列

这就是涉及到了我们的去重操作,在前面都有提到过,关于组合和子集的去重方式。

转换为树的结构来看

 分为了树枝去重和树层去重,这个题是数层去重,也就是同一层,前面用过的元素后面不能再用了。

但是树枝是可以重复使用的。

首先要做的就是对nums数组进行排序,通过相邻的数字判断是否有被用过。

回溯三部曲:

                递归参数:nums,index

                终止条件:同样的,如果path的长度等于数组的长度,说明找到了一组

                单层循环逻辑:if  i>0&当前元素等于前一个元素&并且前一个元素没有被使用过

那么就continue循环。否则加入path 然后递归回溯撤销一起走

为什么这里我们要判断上一个元素没有被使用过呢?

实际上是因为我们第一次在做撤销选择的时候,将他的状态码改为了false。实际上在这一层他是已经使用过的。

代码:

def permuteUnique(self, nums: List[int]) -> List[List[int]]:#路径长度n = len(nums)nums.sort()#答案数组res = []#路径数组path = []#当前状态stats = [False] * ndef dfs(index,nums):if len(path)==n:res.append(path[:])return for i in range(n):if stats[i]==False:'''如果上一个数字和当前数字相同并且上一个数字没有被使用过,那就继续循环'''if i >0 and nums[i-1]==nums[i] and stats[i-1]==False:continuepath.append(nums[i])stats[i]=True#回溯dfs(0,nums)stats[i]=Falsepath.pop()dfs(0,nums)return res

 leetcode491递增子序列

力扣

思路: 

这个递增子序列比较像是取有序的子集。而且本题也要求不能有相同的递增子序列。

这又是子集,又是去重,是不是不由自主的想起了刚刚讲过的90.子集II (opens new window)。

就是因为太像了,更要注意差别所在,要不就掉坑里了!

在90.子集II (opens new window)中我们是通过排序,再加一个标记数组来达到去重的目的。

而本题求自增子序列,是不能对原数组经行排序的,排完序的数组都是自增子序列了。

所以不能使用之前的去重逻辑!

本题给出的示例,还是一个有序数组 [4, 6, 7, 7],这更容易误导大家按照排序的思路去做了。

为了有鲜明的对比,我用[4, 7, 6, 7]这个数组来举例,抽象为树形结构如图:

 首先明确两点:在树的同一层下,重复的元素不可以使用

                        在树的分支上,要和上一个元素进行对比,因为是递增子序列,所以一定要大于等于上一次的元素。

回溯三部曲:终止条件,当我们的startindex已经等于数组长度的时候,说明遍历完毕,可以return了

                        递归参数:nums,startindex,然后需要初始化我们的path和result结果集

                       单层逻辑:这里我们创建一个set(),深度遍历的时候,每一层都会创建一个新的set判断本层元素是否重复使用

 对path路径进行判断是否为空,如果不为空,那就同时判断上一次的元素也就是path[-1]是否大于我们当前的元素,如果上一个元素大于当前元素,或者当前元素已经在我们的used_set中了,那么久continue。否则,我们就加入used_set&path中,然后递归,然后是我们的撤销 回溯 

def findSubsequences(self, nums: List[int]) -> List[List[int]]:self.path = []self.result = []self.traceback(nums,0)return self.resultdef traceback(self,nums,startindex):if len(self.path) >=2:self.result.append(self.path[:])#终止条件 if startindex==len(nums):return #递归#同层横向遍历# 深度遍历中每一层都会有一个全新的usage_list用于记录本层元素是否重复使用used_set = set() for i in range(startindex,len(nums)):if (self.path and nums[i] < self.path[-1]) or nums[i] in used_set:continueused_set.add(nums[i])self.path.append(nums[i])self.traceback(nums,i+1)self.path.pop()


http://www.ppmy.cn/news/981575.html

相关文章

练习时长两年半的双机热备

1.双机热备技术产生的背景 传统的组网方式如下左图所示&#xff0c;内部用户和外部用户的交互报文全部通过防火墙A。如果防火墙A出现故障&#xff0c;内部网络中所有以防火墙A作为默认网关的主机与外部网络之间的通讯将中断&#xff0c;通讯可靠性无法保证。防火墙作为安全设备…

uniapp微信小程序scroll-view滚动scrollLeft不准确

今天在实现微信小程序的一个横向导航的时候出现了一个问题&#xff0c;就是每次滑到滚动条最右边的时候 scrollLeft的值都不准确 原因&#xff1a;因为每次滚动监听事件都会被调用比较耗费资源系统会默认节流&#xff0c;可以在scroll-view 加一个 throttle“{{false}}” 关闭…

【iOS】KVOKVC原理

1 KVO 键值监听 1.1 KVO简介 KVO的全称是Key-Value Observing&#xff0c;俗称"键值监听"&#xff0c;可以用于监听摸个对象属性值得改变。 KVO一般通过以下三个步骤使用&#xff1a; // 1. 添加监听 [self.student1 addObserver:self forKeyPath:"age"…

UE4/5C++多线程插件制作(十四、MTPAbandonable)

目录 MTPAbandonable h实现 cpp实现 MTPMarco.h 首先是异步任务的宏定义部分:

mybatis日志工厂

前言&#xff1a; 如果一个数据库操作&#xff0c;出现异常&#xff0c;我们需要排错&#xff0c;日志就是最好的助手 官方给我们提供了logImpl&#xff1a;指定 MyBatis 所用日志的具体实现&#xff0c;未指定时将自动查找。 默认工厂&#xff1a; 在配置文件里添加&#xf…

基于Jquery EasyUI JSZip FileSaver的简单使用

一、前言 在前端的项目开发中 &#xff0c;下载文件压缩包是很重要的一个环节&#xff0c;那么怎么下载多个文件并压缩成ZIP下载呢&#xff1f; 二、使用步骤 1、引用库 <script type"text/javascript" src"~/Scripts/comm/jszip.min.js" ></…

C#|无法打开cs文件设计窗口

报错信息&#xff1a;To prevent possible data loss before loading the designer, the following errors must be resolved: 解决方案&#xff1a;实不相瞒我把项目解决方案名称改短了就可以了。。有其他原因或者解决方案望不吝赐教。。

oracle部署与安装

oracle部署是搭建测试环境的一个难点&#xff01;很多人用一周都安装不上! 说明: 安装环境 centos6.5 64bit系统 物理机内存&#xff1a;最小1GB&#xff0c;最大2GB活以上 一、配置linux下oracle的安装环境 准备&#xff1a; a.安装linux系统时应注意 干掉所有的目录分区,…