代码随想录 | Day29 | 2024.01.09 | 回溯05 | 二刷

本文介绍了如何解决全排列和非递减子序列问题,重点在于控制树层结构并使用used数组进行去重,包括对重复元素的处理。通过DFS方法实现算法并提供示例代码。
摘要由CSDN通过智能技术生成

今日题目:

491. 非递减子序列
46. 全排列
47. 全排列 II

今日总结

排列和组合问题都是收集叶子节点,而子集问题则是收集所有节点。今天主要是全排列问题,重点学习下怎么控制树层去重。

491. 非递减子序列

要点

  1. 这一题需要实现树层上的去重,所以需要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. 全排列

要点:

  1. 之前犯了个错误,不应该使用ok的方式进行used去重,因为只要used开辟了空间,ok都是存在的,不会是nil。这里应该老老实实使用true进行判断
  2. 这一题也是在树层上去重,使用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

要点:

  1. 在前一题的基础上添加了重复元素这一条件,所以去重方式要进行改变。这里就使用之前用过的先排序再使用used数组的方式
  2. 注意去重时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]
        }
    }
}
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值