代码随想录算法训练营第29天

44 阅读1分钟

491.非递减子序列

在这段代码中,start和used都有去重的作用,但他们的机制和目的不太一样。
start是为了防止纵向一直选择同一个元素,比如说数组为[1,2,3],有start控制迭代起点可以避免出现[1,1,1]的情况。
used是横向去重,记录当前递归层级中已经使用过的值。如果在同一层级中遇到相同的值,就直接跳过,避免生成重复的子序列。例如数组为[1,2,2],如果没有used,会重复生成两个[1,2]

class Solution:
    def __init__(self):
        self.track=[]
        self.path=[]
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        if len(nums)==0:
            return self.res
        self.backtrack(0,nums)
        return self.path
    def backtrack(self,start,nums):
        if len(self.track)>=2:
            self.path.append(self.track.copy())
        used=set()  #哈希集合防止重复选择相同元素
        for i in range(start,len(nums)):
            if self.track and self.track[-1]>nums[i]:
                continue
            if nums[i] in used:
                continue
            used.add(nums[i])
            self.track.append(nums[i])
            self.backtrack(i+1,nums)
            self.track.pop()
        

46.全排列

class Solution:
    def __init__(self):
        self.track=[]
        self.path=[]
    def permute(self, nums: List[int]) -> List[List[int]]:
        used=[False]*len(nums)
        self.backtrack(nums,used)
        return self.path
    def backtrack(self,nums,used):
        if len(nums)==len(self.track):
            self.path.append(self.track.copy())
            return
        for i in range(len(nums)):
            if used[i]:
                continue
            self.track.append(nums[i])
            used[i]=True
            self.backtrack(nums,used)
            self.track.pop()
            used[i]=False
"""
排列问题需要一个used数组,来判断是否使用过某个数字
不用剪枝,不需要写start
"""

47.全排列Ⅱ

去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了

class Solution:
    def __init__(self):
        self.track=[]
        self.path=[]
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        used=[False]*len(nums)
        self.backtrack(nums,used)
        return self.path
    def backtrack(self,nums,used):
        if len(nums)==len(self.track):
            self.path.append(self.track.copy())
            return
        for i in range(len(nums)):
            if (i>0 and nums[i]==nums[i-1] and used[i-1]==True) or used[i]:
                continue

            self.track.append(nums[i])
            used[i]=True
            self.backtrack(nums,used)
            self.track.pop()
            used[i]=False