递增子序列
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。
示例:
- 输入: [4, 6, 7, 7]
- 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
说明:
- 给定数组的长度不会超过15。
- 数组中的整数范围是 [-100,100]。
- 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
理解自增子序列的概念,这题就和子集II不一样了,自增子序列是 子序列而且递增,并且他们顺序不能变,也就是例如[4, 7,6, 7]这种,[4, 6,7, 7]并不是,因为他跟换了元素的位置顺序。
所以这道题不能够类似子集II那样去重
class Solution:
def __init__(self):
self.paths = []
self.path = []
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
'''
本题求自增子序列,所以不能改变原数组顺序
'''
self.backtracking(nums, 0)
return self.paths
def backtracking(self, nums: List[int], start_index: int):
# 收集结果,同78.子集,仍要置于终止条件之前
if len(self.path) >= 2:
# 本题要求所有的节点
self.paths.append(self.path[:])
# Base Case(可忽略)
if start_index == len(nums):
return
# 单层递归逻辑
# 深度遍历中每一层都会有一个全新的usage_list用于记录本层元素是否重复使用
usage_list = []
# 同层横向遍历
for i in range(start_index, len(nums)):
# 若当前元素值小于前一个时(非递增)或者曾用过,跳入下一循环
if (self.path and nums[i] < self.path[-1]) or nums[i] in usage_list:
continue
usage_list.append(nums[i])
self.path.append(nums[i])
self.backtracking(nums, i+1)
self.path.pop()
全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
- 输入: [1,2,3]
- 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。
但排列问题需要一个used数组,标记已经选择的元素,如图橘黄色部分所示:
class Solution:
def __init__(self):
self.path = []
self.paths = []
def permute(self, nums: List[int]) -> List[List[int]]:
self.used_list = [False] * len(nums)
self.backtrack(nums, self.used_list)
return self.paths
def backtrack(self, nums, used_list):
if len(self.path) == len(nums):
self.paths.append(self.path[:])
return
for i in range(0, len(nums)):
if self.used_list[i] == True:
continue
self.path.append(nums[i])
self.used_list[i] = True
self.backtrack(nums, self.used_list)
self.used_list[i] = False
self.path.pop()
全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
- 输入:nums = [1,1,2]
- 输出: [[1,1,2], [1,2,1], [2,1,1]]
示例 2:
- 输入:nums = [1,2,3]
- 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
- 1 <= nums.length <= 8
- -10 <= nums[i] <= 10
这题相对于上一题来说,就是增加一个去重操作,而且也是树层上去重
class Solution:
def __init__(self):
self.path = []
self.paths = []
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
self.path.clear()
self.paths.clear()
used_list = [False] * len(nums)
nums.sort()
self.backtrack(nums, used_list)
return self.paths
def backtrack(self, nums, used_list):
if len(self.path) == len(nums):
self.paths.append(self.path[:])
return
for i in range(len(nums)):
if not used_list[i]:
if i > 0 and nums[i] == nums[i - 1] and used_list[i -1] == False:
continue
self.path.append(nums[i])
used_list[i] = True
self.backtrack(nums, used_list)
used_list[i] = False
self.path.pop()