算法练习Day23 (Leetcode/Python-回溯算法)

46. Permutations

Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.

Example 1:

Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]思路:此题可用回溯法做排列问题。待取元素的candiate内无重复,区别于之前的组合问题,这里在横向遍历时for循环需要遍历所有元素,而不是在startIndex之后的元素(因为排列可以取[1,2,3],[1,3,2]这样的元素,组合的话就只能取[1,2,3],而无[1,3,2])。但是为了避免与纵向已经取过的元素在一个path里重复,要设置一个used元素记录之前path里已经取过的元素。这个used元素也需要在回溯中调整。
class Solution(object):def backtrack(self, nums, path, result, used):if len(path) == len(nums):result.append(path[:]) # 记得用[:]return for i in range(len(nums)): # use used to remove duplicated itemif used[i]:continueused[i] = Truepath.append(nums[i])self.backtrack(nums, path, result, used)path.pop()used[i] = Falsedef permute(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""result = []used = len(nums) * [False]self.backtrack(nums, [], result, used)return result

491. Non-decreasing Subsequences

Given an integer array nums, return all the different possible non-decreasing subsequences of the given array with at least two elements. You may return the answer in any order.

Example 1:

Input: nums = [4,6,7,7]
Output: [[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

思路:找出一个数组中的所有升序子序列,注意这个子序列不需要在原数组中连续。用递归写出暴力解法的思路枚举出所有可能的子序列就可以了。第i+1层横向遍历从startIndex = i+1开始。

关键点在于去重。其实只要每次横向遍历不用本次横向遍历里已经用过的元素就可以了。因为这个新元素最后可以取得的有效升序子序列之能是之前这个元素可以取得的有效子集。因为有效升序子集不需要连续!!

class Solution(object):def backtrack(self, nums, startIndex, path, result):if len(path) > 1:result.append(path[:])uset = set()for i in range(startIndex, len(nums)):if path and nums[i] < path[-1] or nums[i] in uset:  #[2,7,8,4,7,9]  比如这种情况下,第二个7就不能再被取,因为第二个7能组合出来的有效升序子序列一定能被第一个7组合出来。continueuset.add(nums[i])path.append(nums[i])self.backtrack(nums, i +1, path, result)path.pop()def findSubsequences(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""result = []path = []self.backtrack(nums, 0, path, result)return result 

47. Permutations II

此题乍一看和之前的题很像,应该是一个套路,但是 if (i>0 and nums[i] == nums[i-1] and used[i-1]) or used[i]: 这个两个条件却让我想了很久,这也是此题与之前题目的不同之处。or之后的条件和今天的第一题一致,第一个条件则是结合了排列和元素重复这两个要素得出,可以参见代码随想录里的这个例子。

比如有元素[1,1,1], 第一层取了第一个1,那么第二个和第三个1为避免重复就不可以再取了。进入第二层时,used的情况是[1,0,0]。第二层时,第一个1已经取过了,所以第二层就不可以取第一个1了(对应上述第二中情况),就轮到第二个1了,第二个1之前没有被取过,所以就可以取。第三层时,第一第二个1都不可以取了,就得取第三个1了。

在判断第二层的第二个1是不是要取时,因为第一层时,第一个1已经置true被取过了,且第一层时,第二个1没有被取过,还是false,所以可以取。第二层的第三个1,虽然第一层时第三个元素未被取过还是false,但第二个1也是false,所以为了原数组里重复元素去重,这时候第三个元素不取。

在判断第三层的第二个1是不是要取时,虽然or之前的条件判断可取,但or之后的条件显示因为第二层时,第二个1已经置true被取过了,所以最终不取,但是判断第三层第三个1时,第二层里第二个1被取过了,所以这一层就轮到了第三个1。

以上是我自己目前的理解,不能确定就是完全正确的。如果错漏还请指出。谢谢!

class Solution(object):def backtrack(self, nums, path, result, used):if len(nums) == len(path):result.append(path[:])return for i in range(len(nums)):if (i>0 and nums[i] == nums[i-1] and not used[i-1]) or used[i]:# 1. 不可以读取的情况也就是当前位和之前位置值相同,且之前位置在之前层已经被读取过了,那么接下来就要轮到当前元素被读取了。# 2. 或者是当前位置的值在升序序列中虽然是第一次出现,但是该元素在之前的层被用过,排列中也要去掉这个以去重。# 比如有元素[1,1,1], 第一层取了第一个1,那么第二个和第三个1为避免重复就不可以再取了。进入第二层时,used的情况是[1,0,0]。第二层时,第一个1已经取过了,所以第二层就不可以取第一个1了(对应上述第二中情况),就轮到第二个1了,第二个1之前没有被取过,所以就可以取。第三层时,第一第二个1都不可以取了,就得取第三个1了。continueused[i] = Truepath.append(nums[i])self.backtrack(nums, path, result, used)used[i] = False # 注意!因为回溯,处理每一个元素时,和它同层的元素的情况是未被处理的原始值,看到的处理后的都是上一层的。path.pop()def permuteUnique(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""result = []nums.sort()used = [False] * len(nums)self.backtrack(nums, [], result, used)return result 

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

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

相关文章

【C Primer Plus第六版 学习笔记】 第十六章 C预处理器和C库

有基础&#xff0c;进阶用&#xff0c;个人查漏补缺 第十五章的内容之前学过&#xff0c;跳过 预处理之前&#xff0c;编译器必须对该程序进行一些翻译处理 首先把源代码中出现的字符映射到原字符集 其次编译器定位每个反斜杠后面跟着换行符的实例&#xff0c;并删除它们&…

中科亿海微UART协议

引言 在现代数字系统设计中&#xff0c;通信是一个至关重要的方面。而UART&#xff08;通用异步接收器/发送器&#xff09;协议作为一种常见的串行通信协议&#xff0c;被广泛应用于各种数字系统中。FPGA&#xff08;现场可编程门阵列&#xff09;作为一种灵活可编程的硬件平台…

鸿蒙开发第1篇__网络请求

先访问 OpenAtom OpenHarmony &#xff0c; 浏览 Http数据请求&#xff0c;

【MATLAB】【数字信号处理】基本信号的仿真与实现

目的 1、用MATLAB软件实现冲激序列 2、用MATLAB软件实现阶跃序列 3、用MATLAB软件实现指数序列 4、用MATLAB软件实现正弦序列 内容与测试结果 1、用MATLAB软件实现冲激序列 程序如下&#xff1a; % 1 冲激序列 clc; clear all; n0 -10; nf 50; ns 1; A 1;%起点为-1&…

国家开放大学形成性考核 统一考试 资料参考

试卷代号&#xff1a;11141 工程经济与管理 参考试题 一、单项选择题&#xff08;每题2分&#xff0c;共20分&#xff09; 1.资金的时间价值&#xff08; &#xff09;。 A.现在拥有的资金在将来投资时所能获得的利益 B.现在拥有的资金在将来消费时所付出的福利损失 C.…

实验六——cache模拟器实验

前言 本次实验的主要目的是熟悉cache的原理。加深对cache的映像规则、替换方法、cache命中与缺失的理解。通过实验对比分析映像规则对cache性能的影响。 实验内容一&#xff1a;熟悉模拟程序 阅读给出的cache模拟程序&#xff08;cachesimulator.cpp&#xff09;&#xff0c;…

Feign远程调用丢失请求头问题处理--异步任务执行远程请求线程丢失请求属性问题处理

在关于Feign远程调用丢失请求头问题处理中解决了远程调用发送请求丢失老请求中请求头的问题。A方法接收浏览器中的请求&#xff0c;B方法是A方法中嵌套方法用来发送Feign远程调用。如果B方法是在异步任务CompletableFuture.runAsync(()->{},Executor)中执行并启用线程池分配…

从0到1入门C++编程——02 通讯录管理系统

文章目录 一、创建结构体及菜单显示二、添加联系人三、显示联系人四、删除联系人五、查找联系人六、修改联系人七、清空联系人八、退出通讯录 本文通过C实现一个通讯录管理系统&#xff0c;系统要实现的功能如下。 1、添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息…

Zookeeper-Zookeeper选举源码

看源码方法&#xff1a; 1、先使用&#xff1a;先看官方文档快速掌握框架的基本使用 2、抓主线&#xff1a;找一个demo入手&#xff0c;顺藤摸瓜快速静态看一遍框架的主线源码&#xff0c;画出源码主流程图&#xff0c;切勿一开始就陷入源码的细枝末节&#xff0c;否则会把自…

【分布式微服务专题】SpringSecurity快速入门

目录 前言阅读对象阅读导航前置知识笔记正文一、Spring Security介绍1.1 什么是Spring Security1.2 它是干什么的1.3 Spring Security和Shiro比较 二、快速开始2.1 用户认证2.1.1 设置用户名2.1.1.1 基于application.yml配置文件2.1.1.2 基于Java Config配置方式 2.1.2 设置加密…

71内网安全-域横向网络传输应用层隧道技术

必备知识点&#xff1b; 代理和隧道技术的区别&#xff1f; 代理主要解决的是网络访问问题&#xff0c;隧道是对过滤的绕过&#xff0c; 隧道技术是为了解决什么 解决被防火墙一些设备&#xff0c;ids&#xff08;入侵检测系统&#xff09;进行拦截的东西进行突破&#xff0…