一天一道算法题(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 篇,本系列将持续更新,每篇都提供清晰的思路与编程语言实现。欢迎关注,第一时间获取更新。如果你有想看的题目,也可以在评论区留言告诉我。

相关推荐
拓恒技术2 小时前
无人机巡检AI算法的工程化落地:从需求到交付的5个核心环节
人工智能·算法·无人机
晨曦中的暮雨2 小时前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
怕浪猫2 小时前
Claude Code vs Codex:Computer Use 实现原理深度拆解
算法·面试·github
喵了几个咪2 小时前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
文丑颜不良啊3 小时前
LeetCode876~900题目解析
java·leetcode
罗西的思考4 小时前
AI 时代的 “房谋杜断”:如何培养能力、品味与判断力
人工智能·算法·机器学习
aloha_7894 小时前
Java 基础、集合、异常与 JUnit 5 速查
java·junit·sqlserver
淡海水4 小时前
07-02-源码-.NET Core GC分配路径
算法·unity·c#·.netcore·gc·1024程序员节
在世修行4 小时前
智学文枢:页面切换与跨页数据预填
python·桌面应用·signal·1024程序员节·pyside·跨页跳转·状态预填
知守观4 小时前
设计模式实战:从真实老项目中看标准模板方法与工厂的落地
java·spring·设计模式