LeetCode - Medium - 78,幸亏有这本623页的微服务框架实战笔记

Given an integer array nums of unique elements, return all possible subsets (the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

Example 1:

Input: nums = [1,2,3]

Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

Example 2:

Input: nums = [0]

Output: [[],[0]]

Constraints:

  • 1 <= nums.length <= 10

  • -10 <= nums[i] <= 10

  • All the numbers of nums are unique.

Analysis


方法一:回溯算法

思路分析

如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点

其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。

那么既然是无序,取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始!

那么,什么时候for可以从0开始呢?求排列问题的时候,就要从0开始,因为集合是有序的,{1, 2} 和{2, 1}是两个集合。

以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:

回溯三弄
函数签名

参数含义如下:

  • List<Integer> path:为子集收集元素。

  • int[] originalArray:一开始传入的原数组。

  • int startIndex:下一递归其实索引。

  • List<List<Integer>> result:存放子集组合。

代码如下:

private void backtracking(List path, int[] originalArray,

int startIndex, List<List> result) {}

终止条件

观察思路分析的图,发现剩余集合为空的时候,就是叶子节点。也就是startIndex已经等于数组的长度了,就终止了,因为没有元素可取了,代码如下:

if(startIndex == originalArray.length) {

return;

}

其实可以不需要加终止条件,因为startIndex == originalArray.length,本层for循环本来也结束了。

遍历顺序

求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。

代码如下:

for (int i = startIndex; i < originalArray.length; i++) {

path.add(originalArray[i]);

backtracking(path, originalArray, i + 1, result);

path.remove(path.size() - 1);

}

方法二:BFS

Using [1, 2, 3] as an example, the iterative process is like:

  1. Initially, one empty subset [[]]

  2. Adding 1 to []: [[], [1]];

  3. Adding 2 to [] and [1]: [[], [1], [2], [1, 2]];

  4. Adding 3 to [], [1], [2] and [1, 2]: [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]].

方法三:位操作

| 十进制 | 二进制 |

| — | — |

| 0 | 000 |

| 1 | 001 |

| 2 | 010 |

| 3 | 011 |

| 4 | 100 |

| 5 | 101 |

| 6 | 110 |

| 7 | 111 |

对例一来说:

Input: nums = [1,2,3]

Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

让二进制与无重集合相结合,0表示对应的数不加入集合,1表示对应的数加入集合,如下表:

| - | nums[2]:3 | nums[1]:2 | nums[0]:1 | 子集 |

| — | — | — | — | — |

| 0 | 0 | 0 | 0 | [] |

| 1 | 0 | 0 | 1 | [1] |

| 2 | 0 | 1 | 0 | [2] |

| 3 | 0 | 1 | 1 | [1,2] |

| 4 | 1 | 0 | 0 | [3] |

| 5 | 1 | 0 | 1 | [1,3] |

| 6 | 1 | 1 | 0 | [2,3] |

| 7 | 1 | 1 | 1 | [1,2,3] |

What a happy accident!

参考资料

  1. 回溯算法:求子集问题!

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后希望可以帮助到大家!

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

image

(2)刷的算法题(还有左神的算法笔记)

image

(3)面经+真题解析+对应的相关笔记(很全面)

image

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!
!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

[外链图片转存中…(img-BbSLWAoq-1711760700792)]

(2)刷的算法题(还有左神的算法笔记)

[外链图片转存中…(img-OIMWuGAX-1711760700793)]

(3)面经+真题解析+对应的相关笔记(很全面)

[外链图片转存中…(img-RyaE1Mc7-1711760700793)]

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值