一天一道算法题(34):回溯法的经典例题(子集)

78. 子集

文章目录

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

text

复制代码
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

text

复制代码
输入:nums = [0]
输出:[[],[0]]

思路

  • 这道题和全排列一样,都是递归的经典题,但子集比全排列多了一个"顺序无关"的限制。全排列里 [1,2][2,1] 是两个答案,但子集里它们是同一个。所以这道题递归的核心就变成了:怎么保证下一层只从当前位置往后选。下面用回溯法写一下

- 回溯法

  • 这里我们用闭包的方式,不需要传结果集的指针

  • 使用到的参数有

    1. ans 用来记录结果集
    2. path 当前子集
    3. start 下一层枚举的起点
  • go

    go 复制代码
    func subsets(nums []int) [][]int {
        ans := make([][]int, 0)
        path := make([]int, 0)
        length := len(nums)
    
        var dfs func(start int)
        dfs = func(start int) {
            //每进入一层,当前 path 就是一个合法子集
            tmp := append([]int(nil), path...)
            ans = append(ans, tmp)
    
            //从 start 开始枚举,保证顺序不重复
            for i := start; i < length; i++ {
                path = append(path, nums[i])
                dfs(i + 1)
                //回溯
                path = path[:len(path)-1]
            }
        }
    
        dfs(0)
        return ans
    }
  • 还有一个容易踩的坑:ans = append(ans, path) 这样写是错的,因为 path 是复用的切片,后续 append 和截断会改到底层数组。必须像上面那样拷贝一份 tmp 再存

结语

本文是 《算法题目解析系列》 的第 34 篇,本系列将持续更新,每篇都提供清晰的思路与编程语言实现。欢迎关注,第一时间获取更新。如果你有想看的题目,也可以在评论区留言告诉我。

相关推荐
ThornArmor2 小时前
重铸1996|肉体渲染:关节的裂缝:分段模型积木拼装与未成熟的 RSP 矩阵骨骼动画形变
c语言·汇编·c++·python·硬件架构·游戏机
毕业设计7032 小时前
(免费领源码)基于Python的博物馆研学活动管理系统的设计与实现22724- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
python·mysql·随机森林·pycharm·django·flask·推荐算法
kyrie_sakura2 小时前
python学习笔记15 -- Anaconda,Jupyter,numpy
python·学习·jupyter·numpy
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之JWT核心概念与实战
java·spring·log4j
Dreams_l2 小时前
死信队列和延迟队列介绍
java·开发语言
Bs_MoneyMagnet2 小时前
基于springboot+vue的生态果园采摘预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·计算机毕业设计
测试老哥3 小时前
接口测试的测试用例应该怎么写?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
麻瓜code3 小时前
【JUC】AQS enq() 自旋入队
java
Zenova EdgeOS3 小时前
Python 工业边缘 redis-py 异步实战
开发语言·redis·python