【LeetCode每日一题】——90.子集 II

这篇博客主要介绍了如何使用回溯算法解决数组子集(幂集)问题,特别是处理有重复元素的情况。文章提供了详细的解题思路、代码实现(Java和C语言版本)以及时间复杂度和空间复杂度分析。示例展示了包括重复元素在内的所有可能子集。
摘要由CSDN通过智能技术生成

一【题目类别】

  • 数组

二【题目难度】

  • 中等

三【题目编号】

  • 90.子集 II

四【题目描述】

  • 给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
  • 解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

五【题目示例】

  • 示例 1:

    • 输入:nums = [1,2,2]
    • 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
  • 示例 2:

    • 输入:nums = [0]
    • 输出:[[],[0]]

六【解题思路】

  • 本题是回溯算法(有重复)的典型应用,关于回溯问题(有重复)的处理步骤如下:
void backTracking(参数)
{
	if(终止条件)
	{
		保存结果;
		return;
	}
	for(遍历从当前位置出发的所有“路径”)
	{
		if(大于开始位置 && 当前元素和前一个元素相同)
        {
            continue;
        }
		保存“路径”节点;
		backTracking(所需参数);
		回溯处理,删除上一步保存的“路径”节点,准备进行新的递归
	}
}
  • 本题也是这个处理步骤,只是不需要递归终止条件的设置,因为遍历完数组也相当于结束了
  • 最后返回结果即可

七【题目提示】

  • 1 < = n u m s . l e n g t h < = 10 1 <= nums.length <= 10 1<=nums.length<=10
  • − 10 < = n u m s [ i ] < = 10 -10 <= nums[i] <= 10 10<=nums[i]<=10

八【时间频度】

  • 时间复杂度: O ( n × 2 n ) O(n×2^n) O(n×2n),其中 n n n为输入数组的大小,因为共 2 n 2^n 2n种状态,每种状态需要 O ( n ) O(n) O(n)的时间来构造
  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n为输入数组的大小

九【代码实现】

  1. Java语言版
package Array;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author: IronmanJay
 * @Description: 90.子集 II
 * @CreateTime: 2022-11-25  09:04
 */
public class p90_SubsetsII {

    public static void main(String[] args) {
        int[] nums = {1, 2, 2};
        List<List<Integer>> res = subsetsWithDup(nums);
        System.out.println("res = " + res);
    }

    public static List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        dfs_back_p90_SubsetsII(nums, res, path, 0);
        return res;
    }

    public static void dfs_back_p90_SubsetsII(int[] nums, List<List<Integer>> res, List<Integer> path, int start) {
        res.add(new ArrayList<>(path));
        for (int i = start; i < nums.length; i++) {
            if (i > start && nums[i] == nums[i - 1]) {
                continue;
            }
            path.add(nums[i]);
            dfs_back_p90_SubsetsII(nums, res, path, i + 1);
            path.remove(path.size() - 1);
        }
    }

}
  1. C语言版
#include<stdio.h>
#include<stdlib.h>

int compare_p90_SubsetsII(const void *a, const void *b)
{
	return *(int *)a - *(int *)b;
}

void dfs_back_p90_SubsetsII(int* nums, int numsSize, int** res, int* returnSize, int** returnColumnSizes, int* path, int pathSize, int start)
{
	res[*returnSize] = (int*)malloc(sizeof(int) * pathSize);
	memcpy(res[*returnSize], path, sizeof(int) * pathSize);
	(*returnColumnSizes)[*returnSize] = pathSize;
	(*returnSize)++;
	for (int i = start; i < numsSize; i++)
	{
		if (i > start && nums[i] == nums[i - 1])
		{
			continue;
		}
		path[pathSize++] = nums[i];
		dfs_back_p90_SubsetsII(nums, numsSize, res, returnSize, returnColumnSizes, path, pathSize, i + 1);
		pathSize--;
	}
}

int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
	qsort(nums, numsSize, sizeof(int), compare_p90_SubsetsII);
	*returnSize = 0;
	*returnColumnSizes = (int*)malloc(sizeof(int) * 10001);
	int** res = (int**)malloc(sizeof(int*) * 10001);
	int* path = (int*)malloc(sizeof(int) * numsSize);
	dfs_back_p90_SubsetsII(nums, numsSize, res, returnSize, returnColumnSizes, path, 0, 0);
	return res;
}

/*主函数省略*/

十【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. C语言版
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值