我的“回溯法”

前言

  • 上课听课不认真,简单听了一下回溯法的基本思想,照葫芦画瓢的写了下面的解法,结果很不理想。
  • 因此写下此博客以自省。

题目

给你一个整数数组 nums ,其中不包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

  • 示例 1:

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

  • 示例2:

输入:nums = [0]
输出:[[],[0]]

我的思路

  • 我的思想是先根据列表的长度产生所有对应长度的二进制数。
  • 然后根据二进制的1,0来决定列表对应位置的数的取与不取。
  • 最后将所有的列表整合到一个列表中。
  • 这样做最后的结果很不理想,时间复杂度和空间复杂度都很高,来看看真正的回溯法改怎么写。

真正的回溯法

  • 未探索区域:剩余的未搜索的数组 nums[index: N - 1] ;
  • 每个 path 是否满足题目的条件: 任何一个 path 都是子集,都满足条件,都要放到 res 中 ;
  • 当前 path 满足条件时,是否继续搜索:是的,找到 nums[0:index-1] 中的子集之后, nums[index] 添加到老的 path 中会形成新的子集。
  • 未探索区域当前可能的选择:每次选择可以选取 s 的 1 个字符,即 nums[index] ;
  • 当前选择符合要求:任何 nums[index] 都是符合要求的,直接放到 path 中;
  • 新的未探索区域:nums 在 index 之后的剩余字符串, nums[index + 1 : N - 1] 。
  • 回溯法的整体思路是:搜索每一条路,每次回溯是对具体的一条路径而言的。对当前搜索路径下的的未探索区域进行搜索,则可能有两种情况:
  1. 当前未搜索区域满足结束条件,则保存当前路径并退出当前搜索;
  2. 当前未搜索区域需要继续搜索,则遍历当前所有可能的选择:如果该选择符合要求,则把当前选择加入当前的搜索路径中,并继续搜索新的未探索区域。

回溯法搜索可行解的模板

res = []
path = []

def backtrack(未探索区域, res, path):
    if path 满足条件:
        res.add(path) # 深度拷贝
        # return  # 如果不用继续搜索需要 return
    for 选择 in 未探索区域当前可能的选择:
        if 当前选择符合要求:
            path.add(当前选择)
            backtrack(新的未探索区域, res, path)
            path.pop()

答案

  • 我的“回溯法”
import numpy as np

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
    	
        data = np.array(nums)
        data = np.unique(data)
        pre = np.power(2,len(data))
        Rres = []
        for i in range(0,pre):
            res = []
            tree = []
            num = len(data)+2-len(bin(i))
            while(num> 0):
                tree.append('0')
                num-=1
            for j in range(2,len(data)+2,1):
                try:
                    tree.append(bin(i)[j])
                except IndexError:
                    continue

            for i in range(0,len(data)):
                if tree[i] == '1':
                    res.append(int(data[i]))
            res.sort()
            if res not in Rres:
                Rres.append(res)
        return Rres
  • 大佬的回溯法
class Solution(object):
    def subsets(self, nums):
        res, path = [], []
        self.dfs(nums, 0, res, path)
        return res
    
    def dfs(self, nums, index, res, path):
        res.append(copy.deepcopy(path))
        for i in range(index, len(nums)):
            path.append(nums[i])
            self.dfs(nums, i + 1, res, path)
            path.pop()

后记

  • 此文章为个人力扣题目小记
  • 部分内容摘自力扣题解部分,但摘的大部分是我个人力扣的题解,如其他地方有侵权,请联系删除。

你可能感兴趣的:(小记,算法,python,回溯法,踩坑,递归)