力扣第90题:带重复元素的子集

力扣第90题:带重复元素的子集

问题描述

给定一个整数数组nums,该数组可能包含重复元素。返回该数组所有可能的子集(幂集),并且子集中的元素需要去重。返回的子集中的每个元素应按照非递减顺序排列。

例如,对于输入数组 [1, 2, 2],应返回:

[[], [1], [1,2], [1,2,2], [2], [2,2]]
思路与算法

这道题的核心是生成所有子集,并且确保在存在重复元素的情况下,跳过重复的子集。我们可以使用 回溯算法 来实现这一点。

1. 排序

首先,我们对数组 nums 进行排序。这样一来,我们可以在生成子集时,跳过相同的元素,避免重复生成相同的子集。

2. 回溯

我们可以通过回溯来生成所有的子集。每次选择一个元素,将其加入到当前的子集中,并递归生成后续的子集。递归的过程中,当遇到重复的元素时,我们跳过它们,从而避免生成重复的子集。

3. 空间管理

每当找到一个子集时,我们需要将其存储起来。为了存储所有的子集,我们使用二维数组 result。此外,我们还需要一个一维数组 returnColumnSizes 来记录每个子集的大小。

代码实现

以下是代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 回溯函数生成所有子集 
void backtrack(int* nums, int numsSize, int** result, int* returnColumnSizes, int* subset, int subsetSize, int start, int* returnSize) { // 创建一个当前子集的副本 result[*returnSize] = (int*)malloc(subsetSize * sizeof(int)); for (int i = 0; i < subsetSize; i++) { result[*returnSize][i] = subset[i]; } returnColumnSizes[*returnSize] = subsetSize; (*returnSize)++; // 继续生成子集 for (int i = start; i < numsSize; i++) { // 跳过重复的元素 if (i > start && nums[i] == nums[i - 1]) { continue; } subset[subsetSize] = nums[i]; backtrack(nums, numsSize, result, returnColumnSizes, subset, subsetSize + 1, i + 1, returnSize); } 
} int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) { // 排序,确保重复元素可以被跳过 qsort(nums, numsSize, sizeof(int), (int(*)(const void*, const void*))strcmp); int maxSubsets = 1 << numsSize; // 子集总数是 2^n int** result = (int**)malloc(maxSubsets * sizeof(int*)); *returnColumnSizes = (int*)malloc(maxSubsets * sizeof(int)); *returnSize = 0; int* subset = (int*)malloc(numsSize * sizeof(int)); // 临时存储一个子集 backtrack(nums, numsSize, result, *returnColumnSizes, subset, 0, 0, returnSize); free(subset); return result; 
} // 打印二维数组
void printSubsets(int** result, int* returnColumnSizes, int returnSize) {for (int i = 0; i < returnSize; i++) {printf("[");for (int j = 0; j < returnColumnSizes[i]; j++) {printf("%d", result[i][j]);if (j < returnColumnSizes[i] - 1) {printf(", ");}}printf("]\n");}
}int main() {int nums[] = {1, 2, 2};int numsSize = sizeof(nums) / sizeof(nums[0]);int returnSize = 0;int* returnColumnSizes = NULL;int** result = subsetsWithDup(nums, numsSize, &returnSize, &returnColumnSizes);printSubsets(result, returnColumnSizes, returnSize);// 释放内存for (int i = 0; i < returnSize; i++) {free(result[i]);}free(result);free(returnColumnSizes);return 0;
}
代码解释
1. backtrack 函数

backtrack 是核心的递归回溯函数。它用于生成所有的子集。

  • 输入参数

    • nums:输入数组,包含整数元素。
    • numsSizenums 的大小。
    • result:二维数组,用于存储生成的所有子集。
    • returnColumnSizes:一维数组,用于存储每个子集的大小。
    • subset:临时数组,用于存储当前子集。
    • subsetSize:当前子集的大小。
    • start:搜索的起始索引。
    • returnSize:当前已生成的子集数量。
  • 算法

    • 将当前子集存储到 result 中。
    • 递归生成子集,从 start 索引开始,避免重复元素。
    • 在递归过程中,通过 if (i > start && nums[i] == nums[i - 1]) 来跳过重复元素。
2. subsetsWithDup 函数

subsetsWithDup 函数是主函数,它首先对输入数组进行排序,以确保可以跳过重复的元素。然后,它调用 backtrack 函数来生成所有子集。

  • 输入参数

    • nums:输入的整数数组。
    • numsSize:数组的大小。
    • returnSize:用来返回子集的数量。
    • returnColumnSizes:用来返回每个子集的大小。
  • 算法

    • 排序 nums 数组。
    • 使用 backtrack 递归生成所有子集。
    • 最后,返回存储所有子集的二维数组 result
3. 内存管理
  • 每次创建一个新的子集时,我们通过 malloc 动态分配内存。递归结束后,result 中的每个子集都需要释放内存。
4. printSubsets 函数

printSubsets 用于打印生成的所有子集。每个子集打印时,按照子集中的元素顺序输出,子集之间用逗号分隔。

时间复杂度分析
  • 排序数组的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组的大小。
  • 回溯生成子集的时间复杂度为 O ( 2 n ) O(2^n) O(2n),因为总共有 2 n 2^n 2n 个子集需要生成。
  • 因此,整体时间复杂度为 O ( n log ⁡ n + 2 n ) O(n \log n + 2^n) O(nlogn+2n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/62952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg 4.3 音视频-多路H265监控录放C++开发十九,ffmpeg封装

封装就是将 一个h264&#xff0c;和一个aac文件重新封装成一个mp4文件。 这里我们的h264 和 aac都是来源于另一个mp4文件&#xff0c;也就是说&#xff0c;我们会将 in.mp4文件解封装成一路videoavstream 和 一路 audioavstream&#xff0c;然后 将这两路的 avstream 合并成一…

LVS默认的工作模式支持哪些负载均衡算法?

LVS默认的工作模式支持哪些负载均衡算法? LVS&#xff08;Linux Virtual Server&#xff09;默认支持多种负载均衡算法&#xff0c;这些算法在不同的场景下具有各自的优势。以下是 LVS 默认支持的负载均衡算法及其特点&#xff1a; 1. 轮询调度&#xff08;Round Robin Sched…

汇编语言学习-二

好吧&#xff0c;已经隔了两天&#xff0c;下完班看了两天&#xff0c;在电脑上装了虚拟机版的MS_DOS,主要是怕折腾坏我的电脑系统&#xff1b; 这个第二天应该是称为第二章更为合适&#xff0c;目前第二章已经看完&#xff0c;基本的命令也是敲了敲&#xff1b; 下面就进行一…

等差数列末项计算

等差数列末项计算 C语言代码C 代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 给出一个等差数列的前两项a1&#xff0c;a2&#xff0c;求第n项是多少。 输入 一行&#xff0c;包含三个整数a1&#xff0c;a2&#x…

【笔记2-1】ESP32:基于vscode的espidf插件的开发环境搭建

主要参考b站宸芯IOT老师的视频&#xff0c;记录自己的笔记&#xff0c;老师讲的主要是linux环境&#xff0c;但配置过程实在太多问题&#xff0c;就直接用windows环境了&#xff0c;老师也有讲一些windows的操作&#xff0c;只要代码会写&#xff0c;操作都还好&#xff0c;开发…

Redis设计与实现第17章 -- 集群 总结2(执行命令 重新分片)

17.3 在集群中执行命令 接收命令的节点会计算出命令要处理的数据库键属于哪个槽&#xff0c;并检查这个槽是否指派给了自己&#xff1a; 如果是的话&#xff0c;直接执行这个命令 否则&#xff0c;节点向客户端返回一个MOVED错误&#xff0c;指引客户端转向redirect至正确的节…

基于Java Springboot蛋糕订购小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

如何在GitHub上Clone项目:一步步指南

GitHub作为全球最大的代码托管平台&#xff0c;汇聚了无数开发者的智慧结晶。对于初学者和资深开发者来说&#xff0c;学会如何从GitHub上克隆&#xff08;Clone&#xff09;项目是一项基本且重要的技能。本文将详细介绍如何在GitHub上克隆项目的步骤&#xff0c;帮助你轻松将他…

使用Postman搞定各种接口token实战

现在许多项目都使用jwt来实现用户登录和数据权限&#xff0c;校验过用户的用户名和密码后&#xff0c;会向用户响应一段经过加密的token&#xff0c;在这段token中可能储存了数据权限等&#xff0c;在后期的访问中&#xff0c;需要携带这段token&#xff0c;后台解析这段token才…

脚本数据库操作 -- 查表、增加字段、备忘录

一、查询数据库中所有表 在MySQL中&#xff0c;您可以使用INFORMATION_SCHEMA数据库来查询数据库中所有表的列表。INFORMATION_SCHEMA是一个特殊的数据库&#xff0c;它包含了关于其他所有数据库的元数据。 以下是查询当前数据库中所有表的SQL语句&#xff1a; SELECT TABLE…

H3C OSPF实验

实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF &#xff0c;实现全网互通为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 实验解法 一、配置IP地址 [R1]int l0 [R1-LoopBack0]ip add 1.1.1.1 32 […

LSTM-CNN-BP-RF-SVM五模型咖喱融合策略混合预测模型

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 LSTM-CNN-BP-RF-SVM五模型咖喱融合策略混合预测模型 Matlab代码注释清晰。 程序设计 完整程序和数据获取方式&#xff1a;私信博主回复LSTM-CNN-BP-RF-SVM五模型咖喱融合策略混合预测模型&#xff08;Matlab&#…

flutter 报错 error: unable to find git in your path.

项目issue&#xff1a;WIndows: "Unable to find git in your PATH." if terminal is not in admin mode Issue #123995 flutter/flutter 解决办法&#xff0c; 方法一&#xff1a;每次想要运行flutter的时候以管理员方式运行&#xff0c;比如以管理方式运行vsco…

Ai编程cursor + sealos + devBox实现登录以及用户管理增删改查(十三)

一、什么是 Sealos&#xff1f; Sealos 是一款以 Kubernetes 为内核的云操作系统发行版。它以云原生的方式&#xff0c;抛弃了传统的云计算架构&#xff0c;转向以 Kubernetes 为云内核的新架构&#xff0c;使企业能够像使用个人电脑一样简单地使用云。 二、适用场景 业务运…

CSS学习记录02

CSS颜色 指定颜色是通过使用预定义的颜色名称&#xff0c;或RGB&#xff0c;HEX&#xff0c;HSL&#xff0c;RGBA&#xff0c;HSLA值。 CSS颜色名 在CSS中&#xff0c;可以使用颜色名称来指定颜色&#xff1a; CSS背景色 您可以为HTML元素设置背景色&#xff1a; <h1 s…

用micropython 操作stm32f4单片机实现串口通讯

from buzzer import Buzzer import pyb import machine # 导入 machine 模块以访问硬件功能 import time # 导入 time 模块以使用与时间相关的函数 from TOFSense import TOFSense_F #导入TOFSense_F板块 import binascii #二进制到 ASCII 的转换&#xff08;编码&#xff09…

postman中获取随机数、唯一ID、时间日期(包括当前日期增减)截取指定位数的字符等

在Postman中&#xff0c;您可以使用内置的动态变量和编写脚本的方式来获取随机数、唯一ID、时间日期以及截取指定位数的字符。以下是具体的操作方法&#xff1a; 一、postman中获取随机数、唯一ID、时间日期&#xff08;包括当前日期增减&#xff09;截取指定位数的字符等 获取…

《智能体雏形开发(高阶实操)》开发计划概述

智能体雏形开发计划 通过本计划,逐步完成一个可以真实运行的智能体雏形。 最终完成一个**“用户日志文件生成日报,日报再进一步汇总成周报”**的任务驱动型智能体雏形 第一阶段:基础准备与环境搭建 1. 学习基础知识 了解智能体的概念、类型和技术框架。学习大模型(如阿里…

【VUE3】npm : 无法加载文件 D:\Program\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。

npm : 无法加载文件 D:\Program\nodejs\npm.ps1。未对文件 D:\Program\nodejs\npm.ps1 进行数字签名。无法在当前系统上运行该脚本。有关运行脚本和设置执行策略的详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_ Execution_Policies。…

级联树结构TreeSelect和上级反查

接口返回结构 前端展示格式 前端组件 <template><div ><el-scrollbar height"70vh"><el-tree :data"deptOptions" :props"{ label: label, children: children }" :expand-on-click-node"false":filter-node-me…