LeetCode 491. 递增子序列
题目链接:491. 递增子序列
思路:此题与90. 子集 II有些类似,都可能包含重复元素。但其实有着本质的区别,我们在做子集问题的时候为了去重的简便而对数组进行了排序,但很显然,此题万万不可用排序,题目就是要求我们找其中的递增子序列的。所以为了进行去重的操作,我们需要采用一种新的方法, 比如哈希表或者集合。
Python版本:
class Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, path):
if len(path)>1:
res.append(path[:])
hashset = set()
for i in range(start, len(nums)):
if (len(path)>0 and nums[i]<path[-1]) or nums[i] in hashset:
continue
hashset.add(nums[i])
path.append(nums[i])
backtrack(i+1, path)
path.pop()
res = []
backtrack(0, [])
return res
go版本:
var res [][]int
func findSubsequences(nums []int) [][]int {
res = [][]int{}
path := []int{}
backtrack(0, path, nums)
return res
}
func backtrack(start int, path, nums []int) {
if len(path)>1 {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
}
set := [201]int{}
for i:=start; i<len(nums); i++ {
if (len(path)>0 && nums[i]<path[len(path)-1]) || set[nums[i]+100]==1 {
continue
}
set[nums[i]+100] = 1
path = append(path, nums[i])
backtrack(i+1, path, nums)
path = path[:len(path)-1]
}
}
因为go没有set这种数据结构,又因为题目给定 -100<nums[i]<100,所以创建一个长度大于200的哈希表来代替。
LeetCode 46. 全排列
题目链接:46. 全排列
思路:可以与组合问题进行类比。全排列也是使用基本的回溯步骤,但与组合问题最大的区别在于start(每一次向深度搜索的起始值)的设置,因为全排列每次都需要将所有数组排列进去,所以在每次循环的时候都需要遍历整个数组,而不是range(start, len(nums))。
Python版本:
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, path):
if len(path)==len(nums):
res.append(path[:])
return
for i in range(len(nums)):
# 因为给定数组不含重复数字, 所以可以直接使用path来充当set
if nums[i] in path:
continue
path.append(nums[i])
backtrack(i+1, path)
path.pop()
res = []
backtrack(0, [])
return res
go版本:
var res [][]int
var visited map[int]bool
func permute(nums []int) [][]int {
res = [][]int{}
visited = map[int]bool{}
backtrack([]int{}, nums)
return res
}
func backtrack(path, nums []int) {
if len(path) == len(nums) {
temp := make([]int, len(path))
copy(temp, path)
res = append(res, temp)
}
for _, n := range nums {
if visited[n] {
continue
}
path = append(path, n)
visited[n] = true
backtrack(path, nums)
path = path[:len(path)-1]
visited[n] = false
}
}
LeetCode 47. 全排列 II
题目链接:47. 全排列 II
思路:因为给定数组内可能含有重复数字,所以要有一步去重的操作,之前我们也已经做了很多去重的题目, 去重最核心的思路就是排序+比较相邻数字,代码随想录对去重操作还有深一步的扩展,细说了对树层的去重和树枝的去重,详见此篇。
Python版本:
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
def backtrack(start, path, flag):
if len(path)==n:
res.append(path[:])
return
for i in range(n):
# 去重
if flag[i]:
continue
if i!=0 and nums[i]==nums[i-1] and flag[i-1]==0:
continue
path.append(nums[i])
flag[i] = 1
backtrack(i+1, path, flag)
path.pop()
flag[i] = 0
res = []
flag = [0] * n
nums.sort()
backtrack(0, [], flag)
return res
go版本:
var res [][]int
func permuteUnique(nums []int) [][]int {
res = [][]int{}
backTrack(nums,len(nums),[]int{})
return res
}
func backTrack(nums []int,numsLen int,path []int) {
if len(nums)==0{
p:=make([]int,len(path))
copy(p,path)
res = append(res,p)
}
used := [21]int{}
for i:=0;i<numsLen;i++{
if used[nums[i]+10]==1{
continue
}
cur:=nums[i]
path = append(path,cur)
used[nums[i]+10]=1
nums = append(nums[:i],nums[i+1:]...)
backTrack(nums,len(nums),path)
nums = append(nums[:i],append([]int{cur},nums[i:]...)...)
path = path[:len(path)-1]
}
}