巧妙异或思路解子集问题,面试官叫绝

       题目描述:

       给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
       说明:解集不能包含重复的子集。
       示例:
       输入: nums = [1,2,3]
       输出:
       [
          [3],
          [1],
          [2],
          [1,2,3],
          [1,3],
          [2,3],
          [1,2],
          []
     ] 

先看一张力扣上的图:

可以通过对应二进制位是否为1,判断是否需要该数,由表格可推得总的情况总数是:0~z^n-1

//子集枚举
//按位&:仅当两个都为1时才位1
func subsets(nums []int) (ans [][]int) {
    n := len(nums)
	//运算符优先级<<比<大
	//1<<n 表示结果的个数
    for mask := 0; mask < 1<<n; mask++ {
        set := []int{}
		
        for i, v := range nums {
			//运算符优先级>>比&(按位&)大

			//mask>>i &1 判断第i位是不是1
            if mask>>i &1 > 0 {
                set = append(set, v)
            }
        }
		
        ans = append(ans, append([]int(nil), set...))
    }
    return
}

代码的主要思想在这段:mask>>i &1 > 0    意思是判断第i位是不是1,右移i个和1按位&。看上图可知道,判断该位是否为1,可以知道是否需要该数,如果大于1,则将其放到数组里。

时间复杂度:O(n*2^n)

空间复杂度:O(n)

看下递归的解决方案:

func subsets(nums []int) (ans [][]int) {
    set := []int{}
    var dfs func(int)
    dfs = func(cur int) {
        if cur == len(nums) {
            ans = append(ans, append([]int(nil), set...))
            return
        }
        set = append(set, nums[cur])
        dfs(cur + 1)
        set = set[:len(set)-1]
        dfs(cur + 1)
    }
    dfs(0)
    return
}

每个数可以选择取还是不取

时间空间复杂度同上

参考地址:https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode-solution/

猜你喜欢

转载自blog.csdn.net/ma2595162349/article/details/108897066