tasks for today:
1.491.递增子序列
2.46.全排列
3.47.全排列II
4.332.重新安排行程/57.N皇后/37.解数独(optional)
-------------------------------------------------------------------
1.491.递增子序列
Although this practice looks simnilar to practice 99 (组合II), but in this practice, the difficult part lies in: it needs get rid of repetation, but currently repetation require sorting the nums, however, sorting nums will make the problem chaos, because this is a permutaion challenge.
So sorting should not be considered, we need to figure out other way to do the repetation devoiding.
The solution is using a set to control each level under the same father node should not be used twice.
class Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
# in this practice, the difficult part lies in: it needs get rid of repetation, but currently repetation require sort the nums, however, sorting nums will make the problem chaos, because this is a permutaion challenge.
# so sorting should not be considered, we need to figure out other way to do the repetation devoiding.
# use a set to control each level under the same father node should not be used twice
result = []
path = []
# nums.sort()
# used = [False] * len(nums)
self.backtracking(nums, 0, path, result)
return result
def backtracking(self, nums, startIndex, path, result):
if len(path) >= 2:
result.append(path[:])
used = set()
for i in range(startIndex, len(nums)):
if (path and nums[i] < path[-1]) or (nums[i] in used):
continue
used.add(nums[i])
path.append(nums[i])
self.backtracking(nums, i + 1, path, result)
path.pop()
2.46.全排列
In this practice, this is a permutation problem, the condition is the nums has no repetative elements, so there is no need to to do repetation-free operation;
one key point which is different from combination problem is the startIndex, here, in permutation problem, the startIndex is not needed, because the startIndex is used to control the start point along each branch, but in permutation problem, the sequence difference would result in a different solution.
So the startIndex is not required here, the only control is of the element has been shown in path.
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
self.backtracking(nums, path, result)
return result
def backtracking(self, nums, path, result):
if len(path) == len(nums):
result.append(path[:])
return
for i in range(len(nums)):
if nums[i] in path:
continue
path.append(nums[i])
self.backtracking(nums, path, result)
path.pop()
But this is conditional because there is no repetative element in the nums list, there might be more complicated scenario in next practice because there might be repetitive elements in the nums list, then a used list to record each element's usage.
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
used = [False] * len(nums)
self.backtracking(nums, path, result, used)
return result
def backtracking(self, nums, path, result, used):
if len(path) == len(nums):
result.append(path[:])
return
for i in range(len(nums)):
if used[i]:
continue
used[i] = True
path.append(nums[i])
self.backtracking(nums, path, result, used)
path.pop()
used[i] = False
3.47.全排列II
The key difference between this practice and last practice is that, in this practice, there are repetative elements in the nums list, so aprat from the used list for controlling if the element has been used in once vertical branch, in each level, there also should be a level_control set for recording if one elements has been used, for preventing the repetative result path.
One point is, our previous repetation-free logic by passing in a list for seeing "if i > 0 and nums[i] == nums[i-1] and list[i-1] == False" can also apply in this practice, because this way requires sorting, and sorting will not affect the solution in permutation practice. In this way, both the vertical and the level control can be realized by one list. used = [False] * len(nums). But for this practice, I prefre seperate them for clarity.
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
used = [False] * len(nums)
self.backtracking(nums, path, result, used)
return result
def backtracking(self, nums, path, result, used):
if len(path) == len(nums):
result.append(path[:])
return
# newly added
level_control = set()
for i in range(len(nums)):
# newly amended
if used[i] or (nums[i] in level_control):
continue
level_control.add(nums[i])
used[i] = True
path.append(nums[i])
self.backtracking(nums, path, result, used)
path.pop()
used[i] = False