题号268

方法一:

排序。给一个数组,数组是乱序的,题目的意思是指定了数组元素的个数也限制了数组元素的取值范围找不在里面的元素。例如n=3,取值只能从0,1,2,3里面取,可以想到对其先排序,然后再遍历,如果遇到不存在的就输出。

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        nums.sort()  #因为题干要求了空间,所以没有新建一个数组
        for i in range(len(nums)):
            if nums[i]!=i: #排序后的数组对应进行查找,不存在就返回
                return i
        return len(nums) #

python乱序输出单词字母 python乱序数组_python乱序输出单词字母


方法二:哈希

把数组元素都放到hashset中,对hashset进行遍历查找。比如n=3,取值只能从0,1,2,3里面取,数组为[0,3,2],先把他们通过遍历放到一个hashset中{0,3,2},然后对hashset进行查找,查0,hash拿着这个值取找发现有,查1,没有,查2,也有,查2也有。跟方法一的区别就是没有进行排序,但是进行了一次遍历,还占了空间。

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        hashset = set([]) #定义一个空的hashset
        for i in range(len(nums)): #遍历数组,放入hashset
            hashset.add(nums[i])
        for j in range(len(nums)+1): #查找hashset
            if j not in hashset:   #找不到就返回
                return j

python乱序输出单词字母 python乱序数组_递归_02


方法三:数学公式

有一个数学公式是0~n之间的数字总和: n(n+1)/2
所以这道题我们可以先算n个数的总和total,然后遍历数组计算数组的和sum,total-sum就是缺失值。

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n =len(nums)
        total = n*(n+1)/2
        add = sum(nums)
        dist = total - add
        return int(dist)

python乱序输出单词字母 python乱序数组_结果集_03

题号78

方法一:暴力法

假设现在的数组是[1,2,3]
1.先建立一个空子集
[ ];
2.然后遍历数组的第一个元素,在保留已有空集的基础上,再加一个往已有结果插入新元素的子集,
现在有[ ],[1];
3.遍历数组的第二个元素2,在保留已有结果的基础上,再分别生成加入2的两个结果,
现在有[ ],[ 1],[ 2],[1,2]
4.遍历数组元素3,在保留已有的基础上,再分别往已有结果里插3,
现在有[ ],[ 1],[ 2],[1,2],[3 ],[ 1,3],[ 2,3],[1,2,3]

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = [[]] #建立一个结果集,这个结果集里已经有一个空集了
        for num in nums: #遍历数组中的元素
            res +=[cur+[num]for cur in res] #对当前已在结果集中的集合加num
        return res
#复合代码的拆解表示:
for num in nums:
    for cur in res:
         res+=cur+[num]

这里需要注意一下Python的集合运算规则:[1]+[2]=[1,2]

python乱序输出单词字母 python乱序数组_结果集_04

方法二:回溯法

假设现在的数组是[1,2,3]

它的自己长度最短为0也就是空集,最长为3也就是它本身。那么我们就遍历子集长度和数组中的元素。

1.子集长度为0时:

子集的结果为[ ]

2.子集长度为1时:子集中只有一个元素,数组中有1,2,3,遍历数组,放入1,满足子集长度。

返回上层并清空结果,再进行一次新的递归,放入2,满足子集长度。

返回上层并清空结果,再进行一次新的递归,放入3,满足子集长度。

返回上层并清空结果。

结果集为:[] [1],[2],[3]

python乱序输出单词字母 python乱序数组_结果集_05

3.子集长度为2时,子集中可以有两个元素,遍历数组1,2,3

python乱序输出单词字母 python乱序数组_结果集_06


结果集为:[] [1],[2],[3],[1,2],[1,3],[2,3]

4.子集长度为3时,遍历数组123,就是它本身

python乱序输出单词字母 python乱序数组_python乱序输出单词字母_07

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        #创建一个空的结果集
        res =[] 
        #遍历子集长度从0到n,len不取右区间所以要加一
        for i in range(len(nums)+1):
            #调用递归函数,递归对象是nums,递归判断条件是子集长度i,递归起点是数组的下标0,递归的结果集初始为空,递归的返回结果集
            self.backtracking(nums,i,0,[],res)
        return res
    # 定义递归函数,参数:
    #backtracking的对象nums,每次的长度length,nums开始遍历的索引
    #backtracking过程中的集合,但是可能不符合回溯条件,比如子集长度i=3,但此时只有两个元素,cur保留过程
    #backtracking结果集res
    def backtracking(self,nums:List[int],length:int,index:int,cur,res):     
        #递归终止条件,当前结果集满足回溯长度   
        if len(cur) == length:
            res.append(cur[:])
            return
        #不满足递归终止条件,继续往cur中添加当前遍历元素之后的元素
        for i in range(index,len(nums)): #比如【1,2】,长度不足3,从2开始遍历后面的数组
            cur.append(nums[i]) #每增加一个元素就递归调用检查长度
            self.backtracking(nums,length,i+1,cur,res)
            cur.pop() #删除新的元素返回上层结果

python乱序输出单词字母 python乱序数组_python乱序输出单词字母_08

方法三:DFS

也用到递归,但是与回溯是有区别的。DFS是从1开始,找到最末尾,然后再返回上层还能选的其他选项,而回溯是每次回溯有一定的判定条件就返回。

python乱序输出单词字母 python乱序数组_python乱序输出单词字母_09

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res =[] #创建一个空的结果集
        self.dfs(nums,res,[])
        return res
    def dfs(self,nums: List[int],res,cur):
        res.append(cur)
        for i in range (len(nums)):
            self.dfs(nums[i+1:],res,cur+[nums[i]]) #往深层走,一层一层添加

python乱序输出单词字母 python乱序数组_python乱序输出单词字母_10

题号90

方法一:暴力法

每个元素一一加进去的方法需要做一个改动,因为这个题含有重复元素。在将值加入结果集的时候做一步判断,结果集中是否已存在。但是Python中区分不了[1,2],[2,1],在判断的时候会认为这是两个集合然后加到结果集里。所以要先对数组进行排序,这样就不会出现[1,2],[2,1]的情况

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        res = [[]]
        nums.sort()
        for num in nums:
            res += [i+[num] for i in res if i+[num] not in res]
        return res

python乱序输出单词字母 python乱序数组_递归_11


方法二:回溯法

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        #创建一个空的结果集
        res =[] 
        nums.sort() #排序,防止出现倒序相同的结果集
        #遍历子集长度从0到n,len不取右区间所以要加一
        for i in range(len(nums)+1):
            #调用递归函数,递归对象是nums,递归判断条件是子集长度i,递归起点是数组的下标0,递归的结果集初始为空,递归的返回结果集
            self.backtracking(nums,i,0,[],res)
        return res
    # 定义递归函数,参数:
    #backtracking的对象nums,每次的长度length,nums开始遍历的索引
    #backtracking过程中的集合,但是可能不符合回溯条件,比如子集长度i=3,但此时只有两个元素,cur保留过程
    #backtracking结果集res
    def backtracking(self,nums:List[int],length:int,index:int,cur,res):     
        #递归终止条件,当前结果集满足回溯长度   
        if len(cur) == length:
            res.append(cur[:])
            return
        #不满足递归终止条件,继续往cur中添加当前遍历元素之后的元素
        for i in range(index,len(nums)): #比如【1,2】,长度不足3,从2开始遍历后面的数组
            if i > index and nums[i] = nums[i-1]: #如果下一个元素和当前元素相同,不进行
                  continue
            cur.append(nums[i]) #每增加一个元素就递归调用检查长度
            self.backtracking(nums,length,i+1,cur,res)
            cur.pop() #删除新的元素返回上层结果

方法三

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res =[] #创建一个空的结果集
        nums.sort()
        self.dfs(nums,res,[])
        return res
    def dfs(self,nums: List[int],res,cur):
        res.append(cur)
        for i in range (len(nums)):
             if i > 0 and nums[i] = nums[i-1]: #如果下一个元素和当前元素相同,不进行
                  continue
            self.dfs(nums[i+1:],res,cur+[nums[i]]) #往深层走,一层一层添加