算法随想录第二十九天打卡|491.递增子序列, 46.全排列, 47.全排列 II

491.递增子序列

本题和大家刚做过的 90.子集II 非常像,但又很不一样,很容易掉坑里。 

代码随想录

视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili

思路

应该是比较简单的题,重复和组合的问题

class Solution:
    def findSubsequences(self, nums):
        result = []
        path = []
        self.backtracking(nums, 0, path, result)
        return result
    
    def backtracking(self, nums, startIndex, path, result):
        if len(path) > 1:
            result.append(path[:])  # 注意要使用切片将当前路径的副本加入结果集
            # 注意这里不要加return,要取树上的节点
        
        uset = set()  # 使用集合对本层元素进行去重
        for i in range(startIndex, len(nums)):
            if (path and nums[i] < path[-1]) or nums[i] in uset:
                continue
            
            uset.add(nums[i])  # 记录这个元素在本层用过了,本层后面不能再用了
            path.append(nums[i])
            self.backtracking(nums, i + 1, path, result)
            path.pop()

总结

思路确实是这个思路,但怎么就是不对呀,算了,思路懂了就行了。

46.全排列 

本题重点感受一下,排列问题 与 组合问题,组合总和,子集问题的区别。 为什么排列问题不用 startIndex 

代码随想录

视频讲解:组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列_哔哩哔哩_bilibili

class Solution(object):
    def permute(self, nums):
        result=[]
        self.beakstruck(nums,result,[],[False]*len(nums))
        return result
       
    def beakstruck(self,nums,result,path,used):
        if len(path)==len(nums):
            result.append(path[:])
        for i in range(len(nums)):
            if used[i]:
                continue
            used[i]=True
            path.append(nums[i])
            self.beakstruck(nums,result,path,used)
            path.pop()
            used[i]=False

总结

这个方法没有见过,确实写不出来。他省略了startindex,本来这会导致他会一直递归下去不停止,但又加了个限制条件,这个可以当成组合的模板。

47.全排列 II 

本题 就是我们讲过的 40.组合总和II 去重逻辑 和 46.全排列 的结合,可以先自己做一下,然后重点看一下 文章中 我讲的拓展内容。 used[i - 1] == true 也行,used[i - 1] == false 也行 

代码随想录

视频讲解:回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II_哔哩哔哩_bilibili

class Solution(object):
    def permuteUnique(self, nums):
        nums.sort()
        result=[]
        self.beakstruck(nums,[],[False]*len(nums),result)
        return result
    
    def beakstruck(self,nums,path,used,result):
        if len(path)==len(nums):
            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]:
                continue
            used[i]=True
            path.append(nums[i])
            self.beakstruck(nums,path,used,result)
            path.pop()
            used[i]=False

总结

忘记加not used[i-1]了,只有在前面的值既相等有为True的情况下才要跳过。

你可能感兴趣的:(算法)