491.递增子序列
题目链接:递增子序列
尝试了一下如果下一个元素比当前小就break,但是这个可以是不连续的,所以就没有用了。
缓慢去重
这个走的特别慢,不知道是不是因为去重做的不太好。
class Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
path = []
result = []
def backtracking(nums, index):
if len(path) > 1 and (path not in result):
result.append(path[:])
if index == len(nums):
return
for i in range(index,len(nums)):
if path == [] or (path != [] and nums[i] >= path[-1]):
path.append(nums[i])
#print(i,nums[i],path)
backtracking(nums, (i+1))
path.pop()
backtracking(nums, 0)
return result
use list
这里就是,[4,7,6,7]这种情况下,最后一个7可以走都不走,结果和第一个7是一样的,但因为不能排序,所以不可以用之前的去重方式,试一下use list。
class Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
path = []
result = []
def backtracking(nums, index):
if len(path) > 1:
result.append(path[:])
if index == len(nums):
return
use = set()
for i in range(index,len(nums)):
if (path and nums[i] < path[-1]) or (nums[i] in use):
continue
path.append(nums[i])
use.add(nums[i])
backtracking(nums, (i+1))
path.pop()
backtracking(nums, 0)
return result
捋一下:nums = [4,6,7,7]
- backtracking(nums, 0) 开始
i in range(0,4)
此时i=0 - 加入nums[0],path = [4], use = {4},进backtracking(nums, 1)
i in range(1,4)
此时 i=1,use重置 - 加入nums[1],path = [4,6], use = {6}, 进backtracking(nums, 2)
i in range(2,4)
此时 i=2,use重置 - path符合条件result = [[4,6]]
- 加入nums[2],path = [4,6,7], use = {7}, 进backtracking(nums, 3)
i in range(3,4)
此时 i=3,use重置 - path符合条件result = [[4,6], [4,6,7]]
- 加入nums[3],path = [4,6,7,7], use = {7}, 进backtracking(nums, 4)
i in range(4,4)
没有i了 - path符合条件result = [[4,6], [4,6,7],[4,6,7,7]]
- len(path) == index, 走到return
- 回到backtracking(nums, 3), path = [4,6,7,7], use = {7}, i=3,开始pop
- 去除7,path = [4,6,7], use = {7},出for循环,无事发生,return null
- 回到backtracking(nums, 2), path = [4,6,7], use = {7}, i=2,开始pop
- 加入nums[2],path = [4,6], use = {7}, for继续i=3
nums[3] in use
所以continue
,出for循环,无事发生,return null- 回到backtracking(nums, 1), path = [4,6], use = {6}, i=1,开始pop
- 去除6,path = [4], use = {6}, for继续i=2
- 加入nums[2],path = [4,7], use = {6,7},再次进入backtracking(nums, 3)此时i=3,use重置
- path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7]]
- 加入nums[3],path = [4,7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
- path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7]]
- len(path) == index, 走到return
- 回到backtracking(nums, 3), path = [4,6,7], use = {7}, i=3,开始pop
- path = [4,6], use = {7},出for循环,无事发生,return null
- 回到backtracking(nums, 1), i=2, path = [4,7], use = {6,7}, 开始pop
- 去掉7,path = [4], use = {6,7}, for继续i=3
nums[3] in use
所以continue
,出for循环,无事发生,return null- 回到backtracking(nums, 0), path = [4], use = {4}, i=0, 开始pop
- 去掉4,path = [], use = {4}, for继续i=1
- 加入nums[1],path = [6], use = {4,6},再次进入backtracking(nums, 2)此时i=2,use重置
- 加入nums[2],path = [6,7], use = {7},再次进入backtracking(nums, 3)此时i=3,use重置
- path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7]]
- 加入nums[3],path = [6,7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
- path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7]]
- len(path) == index, 走到return
- 回到backtracking(nums, 3), path = [6,7,7], use = {7}, i=3,开始pop
- path = [6,7], use = {7},出for循环,无事发生,return null
- 回到backtracking(nums, 2), path = [6,7], use = {7}, i=2,开始pop
- 去掉7, path = [6], use = {7}, for继续i=3
nums[3] in use
所以continue
,出for循环,无事发生,return null- 回到backtracking(nums, 0), path = [6], use = {4,6}, i=2,开始pop
- 去掉6,path = [], use = {4,6}, for继续i=3
- 加入nums[3],path = [7], use = {4,6,7},再次进入backtracking(nums, 3)此时i=3,use重置
- 加入nums[3],path = [7,7], use = {7}, 再次进入backtracking(nums, 4)不进循环
- path符合条件result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
- len(path) == index, 走到return
- 回到backtracking(nums, 3),pop完了循环结束
- 回到backtracking(nums, 0), path = [7], use = {4,6,7}, i=3, 开始pop
- 去掉7, path = [], use = {4,6,7}, for循环结束,无事发生,return null
- 最后输出:result = [[4,6], [4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
总结
因为每次进入backtracking(nums, (i+1)),use list都会重置,所以第一次对前面出现过的元素进行操作时是没有影响的。
但是每一层backtracking(nums, i)在进行for循环的过程中,重复的元素就不可以再次使用了,也就是说在同一父节点下的同层上使用过的元素就不能再使用了。
46.全排列
题目链接:全排列
排列问题应该是不能用start index来思考了,因为是排列问题,每个元素都要在,所以用了use list。
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
path = []
result = []
def backtracking(nums,use):
if len(path) == len(nums) or index == len(nums):
result.append(path[:])
return
for i in range(0,len(nums)):
if use[i] == True:
continue
path.append(nums[i])
use[i] = True
backtracking(nums,use)
use[i] = False
path.pop()
use = [False]*len(nums)
backtracking(nums,use)
return result
47.全排列 II
题目链接:全排列 II
有点想不出来,怎么在去重的前提下同一根树枝上还能走完的。
看了解析
这里的去重是
if i>0 and nums[i] == nums[i-1] and use[i-1] == False:
continue
这里use[i-1]是False和True都可以,
- 如果是False的话,就是说前面那个和他相同的元素之前已经走过了,所以这次不走了。
- 如果是True的话,就是说后面有一个一样的元素,所以这次不走了。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
nums.sort()
path = []
result = []
def backtracking(nums,use):
if len(path) == len(nums):
result.append(path[:])
return
for i in range(len(nums)):
if use[i] == False:
if i>0 and nums[i] == nums[i-1] and use[i-1] == False:
continue
path.append(nums[i])
use[i] = True
backtracking(nums,use)
use[i] = False
path.pop()
use = [False]*len(nums)
backtracking(nums,use)
return result