目的

掌握求一个集合所有指定长度子集的思路

引子

给你一个整数数组 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 中的所有元素 互不相同

子集的遍历--找规律

遍历长度为m的集合C_m^n的所有长度为n的子集,有规律嘛?

2-寻找子集的变化规律.gif

子集的遍历--列通项公式1

令子集的索引列表为indexes, 令列表的索引为i,则:
当指针索引列表的最后一位的索引值indexes[n-1]小于m时,下一帧的规律:

indexes[i] += 1

m = 7
n = 4
i = 3
index[i] = 5
index = [0,1,2,5]

子集的遍历--列通项公式2

当指针索引列表的最后一位的索引值indexes[n-1]等于m时,下一帧的规律:
修改指针索引列表当前的指针,让指针索引列表的当前指针指向i的前面一位并赋值给i,在完成列表中i后每一个成员的值为前一个成员的值加1

i=n-1
for ;i>=0&&index[i]==m-1;i--{}
index[i]+=1
for j:=i+1;j<=n-1;j++{
 index[j]=index[j-1]+1
}

m=7
n=4
i=3
index[i]=6
index=[0,1,2,6]

操作:

i--
index[i]+=1
index[i+1]=index[i]+1

结果:

i=2
index[2]=3
index[3]=4
index=[0,1,3,4]

可视化:

子集的遍历--实现自己固定为n的所有子集代码

func getSubSets(nums []int, subSetLength int) [][]int {
    var result [][]int
    var subSet = make([]int, subSetLength)
    var n = len(nums)
    for i := 0; i < subSetLength; i++ {
        subSet[i] = nums[i]
    }
    var initSubSet = make([]int, subSetLength)
    copy(initSubSet, subSet)
    result = append(result, initSubSet)
    var indexes = make([]int, subSetLength)
    for i := 0; i < subSetLength; i++ {
        indexes[i] = i
    }
    for {
        i := subSetLength - 1
        if    i > 0 && indexes[i] == n+i-subSetLength;  {        
        }
        if i < 0 {
            return result
        }
        indexes[i] += 1
        for j := i + 1; j < subSetLength; j++ {
            indexes[j] = indexes[j-1] + 1
        }
        for ; i < subSetLength; i++ {
            subSet[i] = nums[indexes[i]]
        }
        var tempSubSet = make([]int, subSetLength)
        copy(tempSubSet, subSet)
        result = append(result, tempSubSet)
    }
    return result
}

关翔宇
10 声望3 粉丝

即使是一只蜗牛,不停努力的奔跑,也能到达目标