今日题目:
491. 非递减子序列
46. 全排列
47. 全排列 II
今日总结
排列和组合问题都是收集叶子节点,而子集问题则是收集所有节点。今天主要是全排列问题,重点学习下怎么控制树层去重。
491. 非递减子序列
要点
- 这一题需要实现树层上的去重,所以需要used数组。比如 4 6 7 7,不应该出现两次4 6 7的子序列
代码:
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,0)
for i := start;i <len(nums);i++ {
if len(path) > 0 && nums[i] < path[len(path)-1] {
continue
}
if _, ok := used[nums[i]]; ok {
continue
}
path = append(path, nums[i])
dfs(nums, i+1)
path = path[:len(path)-1]
used[nums[i]] = true
}
}
46. 全排列
要点:
- 之前犯了个错误,不应该使用ok的方式进行used去重,因为只要used开辟了空间,ok都是存在的,不会是nil。这里应该老老实实使用true进行判断
- 这一题也是在树层上去重,使用used数组即可
var (
path []int
res [][]int
used map[int]bool
)
func permute(nums []int) [][]int {
path, res = make([]int, 0), make([][]int, 0)
used = make(map[int]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 used[nums[i]] == true {
continue
}
path = append(path, nums[i])
used[nums[i]] = true
dfs(nums)
path = path[:len(path)-1]
used[nums[i]] = false
}
}
47. 全排列 II
要点:
- 在前一题的基础上添加了重复元素这一条件,所以去重方式要进行改变。这里就使用之前用过的先排序再使用used数组的方式
- 注意去重时used[i-1]为false或者true都可以,简单来说就是树层还是树枝上去重的区别,具体就要看代码随想录的内容了
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]
}
}
}