回溯算法的简单使用
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
https://leetcode-cn.com/problems/subsets/solution/shou-hua-tu-jie-zi-ji-hui-su-fa-xiang-jie-wei-yun-/
我模拟了一下递归的工作
func subsets(nums []int) [][]int { // 保存最终结果 result := make([][]int, 0) // 保存中间结果 list := make([]int, 0) backtrack(nums, 0, list, &result) return result } // nums 给定的集合 // pos 下次添加到集合中的元素位置索引 // list 临时结果集合(每次需要复制保存) // result 最终结果 func backtrack(nums []int, pos int, list []int, result *[][]int) { // 把临时结果复制出来保存到最终结果 ans := make([]int, len(list)) copy(ans, list) *result = append(*result, ans) // 选择、处理结果、再撤销选择 //遍历一遍所有字母,选择则加入临时数组,再进行下一步子步骤,子步骤执行完回退 //假设nums=[1,2,3,4,5,6] //第一步:加入1,list=[1] //第二步:递归调用,result=[[],[1]],循环开始,pos=1,加入2,list=[1,2] //第三步:递归调用,result=[[],[1],[1,2]],循环开始,pos=2,list=[1,2,3] //........................................... //result=[[],[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5],[1,2,3,4,5,6]],循环开始,但此时pos=6,len=6,循环不执行,结束最深层递归,返回上一层pos=5减少最后一个元素,list=[1,2,3,4,5] //pos=5 i=6 len=6 循环结束返回上一层 //pos=4 i=4 list=[1,2,3,4] //pos=4 i=5 num[5]=6,list=[1,2,3,4,6],进入子递归。。。。。 //.................... //pos=4 i=6 len=6循环结束返回上一层 //pos=3 i=4 list=[1,2,3,5] //..... list=[1,2,3,5,6] //list数组直接添加当前递归结点的下一个数,即为遍历左结点 //回溯到上一个状态(根结点)需要对临时数组长度减1,并且该次递归结束(这里右节点和根节点一样,所以不用遍历) for i := pos; i < len(nums); i++ { //一直遍历到最底层左叶结点 list = append(list, nums[i]) //递归调用该程序 backtrack(nums, i+1, list, result) //返回上一个状态并结束本次递归 list = list[0 : len(list)-1] } }