刷题记录 回溯算法-14:491. 非递减子序列

题目:491. 非递减子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

示例 1:

输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

示例 2:

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

提示:

  • 1 <= nums.length <= 15
  • -100 <= nums[i] <= 100

一、模式识别

1.子集问题

子集问题是边访问边收集结果,

不仅在回溯树叶节点收集结果,

因此return和收集结果命令不在一起

2.搜索集

单独搜索集,

无重复选取,但可能含有重复元素

终止条件是最简单的访问到终点

3.结果收集条件

结果收集比较特殊,

需要递增序列

且至少两个元素

递增序列可以在实现路径过程中形成,不需要写在结果收集条件中

因此有在结果收集条件体现只少两个元素:

if len(path) >= 2:
    ans.append(path[:])

 在path形成过程中剪去非递增的路径(并配合同层去重):

if (path and ch < path[-1]) or ch in uset:
    continue

二.代码实现

本题只能基于数值哈希去重

used数值集合(set):

class Solution:
    def backtracking(self, nums, start_idx, path, ans):
        if len(path) >= 2:
            ans.append(path[:])
        if start_idx == len(nums):
            return
        
        uset = set()
        for i in range(start_idx, len(nums)):
            ch = nums[i]
            if (path and ch < path[-1]) or ch in uset:
                continue
            path.append(nums[i])
            uset.add(ch)
            self.backtracking(nums, i + 1, path, ans)
            path.pop()
        
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        ans = []
        # nums.sort()
        self.backtracking(nums, 0, [], ans)
        return ans

used数值数组(list): 

class Solution:
    def backtracking(self, nums, start_idx, path, ans):
        if len(path) >= 2:
            ans.append(path[:])
        if start_idx == len(nums):
            return
        
        used = 201 * [False]
        for i in range(start_idx, len(nums)):
            ch = nums[i]
            if (path and ch < path[-1]) or used[ch + 100]:
                continue
            path.append(nums[i])
            used[ch + 100] = True
            self.backtracking(nums, i + 1, path, ans)
            path.pop()
        
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        ans = []
        # nums.sort()
        self.backtracking(nums, 0, [], ans)
        return ans

三、为什么本题不排序也能去重?

1.原因

先直接给结论:因为递增序列的结果收集条件已经实现了异层去重

在上个刷题记录中思考了排序的两重作用,

刷题记录 回溯算法-13:90. 子集 II-优快云博客

因此虽然本题题目要求不能排序

但只保留递增的path的条件保证了path中已经存在的元素不会在path中再次访问

因此只需要同层去重就可以实现去重

因此也就保证了后面的层

2.以后遇到不能排序的情况怎么办?

了解了排序的两重作用大致的解法很明显了

数值哈希 + 某种异层去重的方法

具体的方法需要根据情况,

但有了大致的思考方向遇到新题一脸懵的概率就小了很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值