Leetcode - 491
由于是求递增子序列,如果我们一开始排序的话,就会改变原来的结果,比如[4,7,4,7] 排序后[4,4,7,7] 其包含的子序列之一是4 4 7 7,显然这个序列是不包含在原序列的结果中的,所以这里不能采用排序的方式。
由于题目中注明了 数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。
也就是说 可能存在[1,1]这种情况的序列,所以我们不能在树枝上进行去重,要在数层上去重,树层去重,除了used数组就是用集合了,这里用集合
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
res = []
def backTracking(temp,curr):
nonlocal res
if len(temp) >= 2:
res.append(temp[:])
used_set = set()
for i in range(curr,len(nums)):
if (len(temp) >0 and nums[i] < temp[-1]) or (nums[i] in used_set):
continue
else:
temp.append(nums[i])
used_set.add(nums[i])
backTracking(temp,i+1)
temp.pop()
backTracking([],0)
return res
Leetcode - 46
排列和组合的区别就在于,排列是有序的,[1,2],[2,1]是不同的序列,而在组合中两者视为同一个,所以在遍历的过程中,排列就不需要curr了,因为每一个位置都可以向前遍历和向后遍历,那么如何记录已经进入temp的元素呢,这里我们用一个used数组来标记哪些元素已经被使过了,我们在遍历的过程中碰到在used对应位置为1的元素我们就直接continue,否则进行正常递归流程
由于是全排列,所以将temp的长度等于nums的长度时为终止条件
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
def backTracing(temp,used):
nonlocal res
if len(temp) == len(nums):
res.append(temp[:])
for i in range(0,len(nums)):
if used[i] ==1:
continue
else:
temp.append(nums[i])
used[i] = 1
backTracing(temp,used)
temp.pop()
used[i] = 0
backTracing([],[0] * len(nums))
return res
Leetcode - 47
nums包含重复元素,可以设想,两个重复元素,若均为temp第一个元素,则其可以得到组合是一模一样的,因为他们的剩余可以选择元素是一样的,所以在这里要去重,这里很明显也是一个数层去重。这里不用管顺序,所以可以进行排序,接下来就是used数组和set的应用了
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
def backTracing(temp,used):
nonlocal res
if len(temp) == len(nums):
# if temp not in res:
res.append(temp[:])
return
#因为这里used数组不能做到又记录元素又用于去重,所以这里引入set来用于树层去重
used_set = set()
for i in range(0,len(nums)):
if used[i] ==1 or (used[i] ==0 and nums[i] in used_set):
continue
else:
temp.append(nums[i])
used_set.add(nums[i])
backTracing(temp,used)
temp.pop()
used[i] = 0
backTracing([],[0] * len(nums))
return res