今日题目:
今日总结
学会使用used数组去重,分为全局和函数内两种方式。排列问题需要使用used全局去重并考虑所有叶子节点,可以不用start,第二题使用重复元素的全排列的去重条件要好好研究研究。
491. 递增子序列
要点
- 具有重复元素,这里使用used数组进行去重
- 注意used是在dfs函数内部的,这意味着used只会在递归的当前深度去重。不能是全局去重。
代码:
var (
path []int
res [][]int
)
func findSubsequences(nums []int) [][]int {
path, res = make([]int, 0), make([][]int, 0)
dfs(nums, 0)
return res
}
func dfs(nums []int, start int) {
if len(path) >=2 {
tmp := make([]int , len(path))
copy(tmp, path)
res = append(res, tmp)
}
used := make(map[int]bool, len(nums)) //注意该数组只会考虑本层深度
for i := start; i < len(nums); i++{
if used[nums[i]] { // 去重
continue
}
if len(path) > 0 && nums[i] < path[len(path)-1]{
continue
}
path = append(path, nums[i])
used[nums[i]] = true
dfs(nums, i+1)
path = path[:len(path)-1]
}
}
46. 全排列
要点:
- 排列问题要收集所有叶子,不需要 start。
- 要使用used去重。
var (
path []int
res [][]int
used []bool
)
func permute(nums []int) [][]int {
path, res, used = make([]int, 0), make([][]int, 0), make([]bool, len(nums))
dfs(nums)
return res
}
func dfs(nums []int) { // 不用start也可
if len(path) == len(nums){
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
return
}
for i := 0; i <len(nums); i++{
if used[i]{
continue
}
path = append(path, nums[i])
used[i] = true
dfs(nums)
used[i] = false
path = path[:len(path)-1]
}
}
47. 全排列 II
要点:
- 与前一题的区别就是包括了重复元素,但是难度大了很多。
- 这里需要同时使用sort和used去重
- i > 0 && nums[i] == nums[i-1] && used[i-1] ==true 这个去重条件很有意思,改成 used[i - 1] == false, 也是正确的
var (
path []int
res [][]int
used []bool
)
func permuteUnique(nums []int) [][]int {
sort.Ints(nums)
path, res, used= make([]int, 0), make([][]int, 0), make([]bool, len(nums))
dfs(nums)
return res
}
func dfs(nums []int) {
if len(path) == len(nums) {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
return
}
for i := 0; i < len(nums); i++{
if i > 0 && nums[i] == nums[i-1] && used[i-1] ==true {
continue
}
if used[i] == false{
path = append(path, nums[i])
used[i] = true
dfs(nums)
used[i] = false
path = path[:len(path)-1]
}
}
}