1、
491. Non-decreasing Subsequences
key point : different possible | non-decreasing subsequences | at least two elements | no sort
而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。
所以不能使用之前的去重逻辑!
idea:
1) 使用set()或者数组记录数层tree level上面的重复值
2)(path and nums[i] < path[-1])
:这部分条件是检查当前元素nums[i]
是否小于当前路径path
中的最后一个元素path[-1]
。如果path
为空(长度为0),则条件(path and nums[i] < path[-1])
为False,因为没有最后一个元素可以比较。如果path
不为空,它将检查nums[i]
是否小于path
中的最后一个元素,如果是,则表示当前元素不应该被考虑,因为它会导致重复的子序列。
class Solution(object):
def findSubsequences(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
path = []
result = []
self.backtracking(path, result, 0, nums)
return result
def backtracking(self, path, result, startIndex, nums):
if len(path) > 1:
result.append(path[:])
setused = set()
for i in range(startIndex, len(nums)):
# non decreasing subsequence
#if path and nums[i] > path [i-1]:
# 忘记set数层去重
#path.append(nums[i])
if (path and nums[i] < path[-1]) or nums[i] in setused:
continue # 这里是要设置不在的跳过
setused.add(nums[i])
path.append(nums[i])
self.backtracking(path, result, i + 1, nums)
path.pop()
2、
all the possible permutations
排列
key point: 没有重复元素 | 强调元素顺序
用used数组
1)Determining Recursive Function Arguments
可以从上图得出 path result used
2)Determination of termination conditions
当path size等于总size的时候
当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。
3)single-level search process
这里和77.组合问题 (opens new window)、131.切割问题 (opens new window)和78.子集问题 (opens new window)最大的不同就是for循环里不用startIndex了。
因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。
而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。
for (int i = 0; i < nums.size(); i++) {
if (used[i] == true) continue; // path里已经收录的元素,直接跳过
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
3、
跟之前的题目不同在于,多了一个去重的过程
还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了。
一定要用used数组,跟之前组合不一样,组合是可选used数组也可以直接(i-1)==(i)