【算法】面试题 08.04. 幂集(多语言实现)

106 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情


面试题 08.04. 幂集:

幂集。编写一种方法,返回某集合的所有子集。集合中不包含重复的元素

说明:解集不能包含重复的子集。

样例 1:

 输入: 
 	nums = [1,2,3]
 	
 输出:
	[
	  [3],
	  [1],
	  [2],
	  [1,2,3],
	  [1,3],
	  [2,3],
	  [1,2],
	  []
	]

分析

  • 面对这道算法题目,二当家的陷入了沉思。
  • 由于没有重复数字,所以就是取不重复的任意组合。
  • 假设集合中有n个元素,每个数字都可以选择或者不选择,那么子集的数量就是2n2^n个。

题解

java

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        // 空集合(所有数字都不选)
        ans.add(new ArrayList<>());

        for (int num : nums) {
            // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
            for (int i = 0, j = ans.size(); i < j; i++) {
                List<Integer> list = new ArrayList<>(ans.get(i));
                // 选择当前数字
                list.add(num);
                // 放入结果
                ans.add(list);
            }
        }

        return ans;
    }
}

c

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    *returnSize = 0;
    *returnColumnSizes = (int*) malloc((1 << numsSize) * sizeof (int));
    int** ans = (int**) malloc((1 << numsSize) * sizeof (int*));
    // 空集合(所有数字都不选)
    (*returnColumnSizes)[(*returnSize)++] = 0;
    ans[0] = NULL;

    for (int i = 0; i < numsSize; i++) {
        // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
        for (int j = 0, size = *returnSize; j < size; j++) {
            int size = (*returnColumnSizes)[j];
            // 多申请一个保存当前循环数字
            int* tmp = (int*) malloc((size + 1) * sizeof(int));
            if (size > 0) {
                // 复制原子集
                memcpy(tmp, ans[j], size * sizeof(int));
            }
            // 选择当前数字组成新子集
            tmp[size++] = nums[i];
            
            // 放入结果
            (*returnColumnSizes)[*returnSize] = size;
            ans[(*returnSize)++] = tmp;
        }
    }

    return ans;
}

c++

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ans;
        // 空集合(所有数字都不选)
        ans.push_back({});

        for (int num : nums) {
            // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
            for (int i = 0, j = ans.size(); i < j; i++) {
                vector<int> tmp = ans[i];
                // 选择当前数字
                tmp.emplace_back(num);
                // 放入结果
                ans.emplace_back(tmp);
            }
        }

        return ans;
    }
};

python

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 空集合(所有数字都不选)
        ans = [[], ]
        for num in nums:
            # 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
            ans += [row + [num] for row in ans]
        return ans
        

go

func subsets(nums []int) [][]int {
    ans := make([][]int, 0)
    // 空集合(所有数字都不选)
    ans = append(ans, []int{})
    for _, num := range nums {
        // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
        for i, j := 0, len(ans); i < j; i++ {
            tmp := make([]int, 0)
            tmp = append(tmp, ans[i]...)
            // 选择当前数字
            tmp = append(tmp, num)
            // 放入结果
            ans = append(ans, tmp)
        }
    }
    return ans
}

rust

impl Solution {
    pub fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
        let mut ans = Vec::new();
        // 空集合(所有数字都不选)
        ans.push(Vec::new());

        nums.iter().for_each(|num|{
            // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
            (0..ans.len()).for_each(|i|{
                let mut tmp = ans[i].clone();
                // 选择当前数字
                tmp.push(*num);
                // 放入结果
                ans.push(tmp);
            });
        });

        ans
    }
}

typescript

function subsets(nums: number[]): number[][] {
    // 空集合(所有数字都不选)
    const ans: number[][] = [[]];
    for (let i in nums) {
        // 之前的结果是没有选择当前数字的集合,遍历之前的结果与当前数字组成新的集合,表示选择当前数字的集合
        for (let j in ans) {
            const tmp: number[] = [...ans[j]];
            // 选择当前数字
            tmp.push(nums[i]);
            // 放入结果
            ans.push(tmp);
        }
    }
    return ans;
};

原题传送门:https://leetcode-cn.com/problems/power-set-lcci/


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://juejin.cn/user/2771185768884824/posts 博客原创~