LeetCode每日1题--78. 子集

74 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情

前言

算法的重要性不言而喻!区分度高!

现在学习的门槛低了,只有能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。

说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!

提前入门学习书籍:CPrimerPlus、大话数据结构

image-20220705103735001

刷题网站

代码随想录 (programmercarl.com)

leetcode

我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以

刷题嘛,最重要的就是坚持了!!!

画图软件

OneNote

这个要经常用,遇见不懂的流程的话就拿它画一画!

笔记软件

Typoral

题目

leetcode.cn/problems/su…

解析

求子集问题和我们前面做的分割问题不一样了,前面的分割问题都是找叶子节点。

但子集问题是找树的所有节点

还是和之前一样,把问题抽象成树的结构,如下:

image.png

回溯三部曲

  1. 递归参数
  • 收集元素的集合path
  • 存放结果的result集合
  • 用来遍历的startIndex

给递归函数传入目标数组和用来遍历的startIndex

private void subsetsHelper(int[] nums, int startIndex){
  1. 递归终止的条件

什么时候遍历停止呢?

那就是集合为空的时候停止遍历

if (startIndex >= nums.length){ //终止条件可不加
    return;
}
  1. 单层搜索的逻辑

同样的套路对吧,先得到节点的值然后加入集合,每得到一种组合就把它就到集合path里收集起来

之后再进行递归,得到另一种组合结果,再收集起来

直到递归完成,再把path集合中收集的元素剔除,重新寻找新的组合形式

for (int i = startIndex; i < nums.length; i++){
    path.add(nums[i]);
    subsetsHelper(nums, i + 1);
    path.removeLast();
}

完整代码

image.png

class Solution {
    List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
    LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
    public List<List<Integer>> subsets(int[] nums) {
        subsetsHelper(nums, 0);
        return result;
    }

    private void subsetsHelper(int[] nums, int startIndex){
        result.add(new ArrayList<>(path));//「遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合」。
        if (startIndex >= nums.length){ //终止条件可不加
            return;
        }
        for (int i = startIndex; i < nums.length; i++){
            path.add(nums[i]);
            subsetsHelper(nums, i + 1);
            path.removeLast();
        }
    }
}