491. 递增子序列
1. first idea
class Solution:
def __init__(self):
self.res_list = []
def back_track(self, tmp_path, candidates):
record_list = []
for idx in range(len(candidates)):
if candidates[idx] in record_list:
continue
record_list.append(candidates[idx])
if (len(tmp_path) == 0) or (candidates[idx] >= tmp_path[-1]):
new_tmp_path = tmp_path + [candidates[idx]]
if len(new_tmp_path) > 1:
self.res_list.append(new_tmp_path)
self.back_track(new_tmp_path, candidates[idx + 1:])
del new_tmp_path
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
self.back_track([], nums)
return self.res_list
看了这么多回溯法的题,我觉得终止条件一般就是所有待选的元素都已用完,没有可以继续往下走的就终止了。
当然也有其他的可能,比如求和等于指定值的那种子序列的,就会有额外的终止条件。
遍历也就一般是遍历每个元素,然后看能否加入到加入tmp_path中,但是python的list很有意思,因为他作为参数传进来是引用传递,就算是你拿他append进res_list中,你还是操作的是同一个list,也就是说res_list中的每个元素会共享相同的地址,所以我们只能不断地新构造list,而不是像C++那样传递的时候会构造新的临时变量。
我做了个简单的实验:
果然地址是一致的,那如果你后面做pop,直接就全是空数组了。
去重的话还是要一层内去重,而不是一个branch中去重。
要满足的加入res_list的tmp_list需要满足长度达到2及以上。
2. learning time
1hour
46. 全排列
1. first idea
class Solution:
def __init__(self):
self.res_list = []
def backtracing(self, tmp_path, candidates):
if len(candidates) == 0:
self.res_list.append(tmp_path)
return
for idx in range(len(candidates)):
self.backtracing(tmp_path=tmp_path + [candidates[idx]], candidates=candidates[:idx] + candidates[(idx + 1):])
def permute(self, nums: List[int]) -> List[List[int]]:
self.backtracing([], nums)
return self.res_list
2. learning time
14min.
47. 全排列 II
1. first idea
class Solution:
def __init__(self):
self.res_list = []
def back_trace(self, tmp_path, candidates):
if len(candidates) == 0:
self.res_list.append(tmp_path)
return
record_list = []
for idx in range(len(candidates)):
if candidates[idx] in record_list:
continue
record_list.append(candidates[idx])
self.back_trace(tmp_path + [candidates[idx]], candidates[:idx] + candidates[(idx + 1):])
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
self.back_trace([], nums)
return self.res_list
同 level去重就可以了,很简单。
2. learning time
17min.