Day29 回溯算法part05
491.递增子序列
leetcode链接:491. 非递减子序列 - 力扣(LeetCode)
题意:给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是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]]
重点:去重
在**90.子集II (opens new window)**中我们是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,**是不能对原数组进行排序的,**排完序的数组都是自增子序列了。
去重的原则:同一父节点下的同层上使用过的元素就不能再使用了(树层去重)
在外设置一个uset,用来记录本层中是否有某个元素重复使用,新的一层的uset会重新定义(清空),所以使得uset可以只使用于本层
class Solution:
def __init__(self):
self.res = []
self.path = []
def backtracking(self, nums, start_index):
if len(self.path)>1:
self.res.append(self.path[:])
used = []
for i in range(start_index, len(nums)):
if nums[i] in used or (self.path and self.path[-1]> nums[i]): #去重并且要是递增的控制
continue
self.path.append(nums[i])
used.append(nums[i])
self.backtracking(nums, i+1)
self.path.pop()
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
self.backtracking(nums,0)
return self.res
46.全排列
leetcode题目:46. 全排列 - 力扣(LeetCode)
**题意:**给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
- 输入: [1,2,3]
- 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
题目难度性不大,就是要记录不能重复使用(需要used数组记录path里都放了哪些元素了),同时是每一次都从第一位开始遍历的(每层都是从0开始搜索而不是startIndex)
- 时间复杂度: O(n!)
- 空间复杂度: O(n)
class Solution:
def __init__(self):
self.res = []
self.path = []
def backtracking(self, nums, used):
if len(self.path) == len(nums):
self.res.append(self.path[:])
return
for i in range(len(nums)):
if used[i] == True:
continue
self.path.append(nums[i])
used[i] = True
self.backtracking(nums, used)
self.path.pop()
used[i] = False
def permute(self, nums: List[int]) -> List[List[int]]:
used = [False] *len(nums)
self.backtracking(nums, used)
return self.res
47.全排列 II
leetcode题目:47. 全排列 II - 力扣(LeetCode)
题意:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
- 输入:nums = [1,1,2]
- 输出: [[1,1,2], [1,2,1], [2,1,1]]
去重:树层去重:还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了。
class Solution:
def __init__(self):
self.res = []
self.path = []
def backtracking(self, nums, used):
if len(self.path) == len(nums):
self.res.append(self.path[:])
return
for i in range(len(nums)):
if used[i] == True:
continue
if i>0 and nums[i] == nums[i-1] and used[i-1]== False:
continue
self.path.append(nums[i])
used[i] = True
self.backtracking(nums, used)
self.path.pop()
used[i] = False
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
used = [False] * len(nums)
self.backtracking(sorted(nums), used)
return self.res