代码随想录算法训练营第二十九天

文章详细讨论了如何使用回溯算法解决491.递增子序列和46/47.全排列问题。对于递增子序列,作者对比了两种去重方法,一种是缓慢去重,另一种是使用集合(uselist)实现。全排列问题中,通过使用use列表跟踪已使用的元素来避免重复。在全排列II中,通过判断当前位置元素是否与前一个相同且未被使用来实现去重。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第二十九天|491.递增子序列,46.全排列,47.全排列 II

491.递增子序列

题目链接:递增子序列
尝试了一下如果下一个元素比当前小就break,但是这个可以是不连续的,所以就没有用了。

缓慢去重

这个走的特别慢,不知道是不是因为去重做的不太好。

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        def backtracking(nums, index):
            if len(path) > 1 and (path not in result):
                result.append(path[:])
            
            if index == len(nums):
                return
            
            for i in range(index,len(nums)):
                if path == [] or (path != [] and nums[i] >= path[-1]):
                    path.append(nums[i])
                    #print(i,nums[i],path)
                    backtracking(nums, (i+1))
                    path.pop()
        
        backtracking(nums, 0)
        return result        

use list

这里就是,[4,7,6,7]这种情况下,最后一个7可以走都不走,结果和第一个7是一样的,但因为不能排序,所以不可以用之前的去重方式,试一下use list。

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        def backtracking(nums, index):
            if len(path) > 1:
                result.append(path[:])
            
            if index == len(nums):
                return
            
            use = set()
            for i in range(index,len(nums)):
                if (path and nums[i] < path[-1]) or (nums[i] in use):
                    continue

                path.append(nums[i])
                use.add(nums[i])
                backtracking(nums, (i+1))
                path.pop()
        
        backtracking(nums, 0)
        return result

捋一下:nums = [4,6,7,7]

  • backtracking(nums, 0) 开始i in range(0,4)此时i=0
  • 加入nums[0],path = [4], use = {4},进backtracking(nums, 1) i in range(1,4) 此时 i=1,use重置
  • 加入nums[1],path = [4,6], use = {6}, 进backtracking(nums, 2) i in range(2,4) 此时 i=2,use重置
  • path符合条件result = [[4,6]]
  • 加入nums[2],path = [4,6,7], use = {7}, 进backtracking(nums, 3) i in range(3,4) 此时 i=3,use重置
  • path符合条件result = [[4,6], [4,6,7]]
  • 加入nums[3],path = [4,6,7,7], use = {7}, 进backtracking(nums, 4) i in range(4,4)没有i了
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7]]
  • len(path) == index, 走到return
  • 回到backtracking(nums, 3), path = [4,6,7,7], use = {7}, i=3,开始pop
  • 去除7,path = [4,6,7], use = {7},出for循环,无事发生,return null
  • 回到backtracking(nums, 2), path = [4,6,7], use = {7}, i=2,开始pop
  • 加入nums[2],path = [4,6], use = {7}, for继续i=3
  • nums[3] in use 所以 continue,出for循环,无事发生,return null
  • 回到backtracking(nums, 1), path = [4,6], use = {6}, i=1,开始pop
  • 去除6,path = [4], use = {6}, for继续i=2
  • 加入nums[2],path = [4,7], use = {6,7},再次进入backtracking(nums, 3)此时i=3,use重置
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7]]
  • 加入nums[3],path = [4,7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7]]
  • len(path) == index, 走到return
  • 回到backtracking(nums, 3), path = [4,6,7], use = {7}, i=3,开始pop
  • path = [4,6], use = {7},出for循环,无事发生,return null
  • 回到backtracking(nums, 1), i=2, path = [4,7], use = {6,7}, 开始pop
  • 去掉7,path = [4], use = {6,7}, for继续i=3
  • nums[3] in use 所以 continue,出for循环,无事发生,return null
  • 回到backtracking(nums, 0), path = [4], use = {4}, i=0, 开始pop
  • 去掉4,path = [], use = {4}, for继续i=1
  • 加入nums[1],path = [6], use = {4,6},再次进入backtracking(nums, 2)此时i=2,use重置
  • 加入nums[2],path = [6,7], use = {7},再次进入backtracking(nums, 3)此时i=3,use重置
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7]]
  • 加入nums[3],path = [6,7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7]]
  • len(path) == index, 走到return
  • 回到backtracking(nums, 3), path = [6,7,7], use = {7}, i=3,开始pop
  • path = [6,7], use = {7},出for循环,无事发生,return null
  • 回到backtracking(nums, 2), path = [6,7], use = {7}, i=2,开始pop
  • 去掉7, path = [6], use = {7}, for继续i=3
  • nums[3] in use 所以 continue,出for循环,无事发生,return null
  • 回到backtracking(nums, 0), path = [6], use = {4,6}, i=2,开始pop
  • 去掉6,path = [], use = {4,6}, for继续i=3
  • 加入nums[3],path = [7], use = {4,6,7},再次进入backtracking(nums, 3)此时i=3,use重置
  • 加入nums[3],path = [7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
  • path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
  • len(path) == index, 走到return
  • 回到backtracking(nums, 3),pop完了循环结束
  • 回到backtracking(nums, 0), path = [7], use = {4,6,7}, i=3, 开始pop
  • 去掉7, path = [], use = {4,6,7}, for循环结束,无事发生,return null
  • 最后输出:result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

总结

因为每次进入backtracking(nums, (i+1)),use list都会重置,所以第一次对前面出现过的元素进行操作时是没有影响的。
但是每一层backtracking(nums, i)在进行for循环的过程中,重复的元素就不可以再次使用了,也就是说在同一父节点下的同层上使用过的元素就不能再使用了

46.全排列

题目链接:全排列
排列问题应该是不能用start index来思考了,因为是排列问题,每个元素都要在,所以用了use list。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        def backtracking(nums,use):
            if len(path) == len(nums) or index == len(nums):
                result.append(path[:])
                return
            
            for i in range(0,len(nums)):
                if use[i] == True:
                    continue
                path.append(nums[i])
                use[i] = True
                backtracking(nums,use)
                use[i] = False
                path.pop()
        use = [False]*len(nums)
        backtracking(nums,use)
        return result      

47.全排列 II

题目链接:全排列 II
有点想不出来,怎么在去重的前提下同一根树枝上还能走完的。

看了解析
这里的去重是

if i>0 and nums[i] == nums[i-1] and use[i-1] == False:
	continue

这里use[i-1]是False和True都可以,

  • 如果是False的话,就是说前面那个和他相同的元素之前已经走过了,所以这次不走了。
  • 如果是True的话,就是说后面有一个一样的元素,所以这次不走了。
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        path = []
        result = []
        def backtracking(nums,use):
            if len(path) == len(nums):
                result.append(path[:])
                return

            for i in range(len(nums)):
                if use[i] == False:
                    if i>0 and nums[i] == nums[i-1] and use[i-1] == False:
                        continue
                    path.append(nums[i])
                    use[i] = True
                    backtracking(nums,use)
                    use[i] = False
                    path.pop()
        use = [False]*len(nums)
        backtracking(nums,use)
        return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值