现代计算框架下的子集枚举:迭代法与动态规划的综合分析【力扣90】

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
python源码解读
程序员必备的数学知识与应用
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

题目描述

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

解集不能包含重复的子集。

输入格式
  • nums:一个整数数组,可能包含重复元素。
输出格式
  • 返回所有可能的子集列表。

示例

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

方法一:回溯法

解题步骤
  1. 排序:首先对数组进行排序,以方便处理重复元素。
  2. 递归构建:使用递归方法,针对每个元素选择“使用”或“不使用”,并跳过重复元素。
完整的规范代码
def subsetsWithDup(nums):
    """
    使用回溯法生成所有可能的子集,处理重复元素
    :param nums: List[int], 输入的整数数组
    :return: List[List[int]], 所有可能的子集
    """
    nums.sort()  # 排序以方便处理重复元素
    results = []
    def backtrack(start, path):
        results.append(path[:])  # 添加当前子集
        for i in range(start, len(nums)):
            if i > start and nums[i] == nums[i-1]:
                continue  # 跳过重复元素
            path.append(nums[i])
            backtrack(i + 1, path)
            path.pop()

    backtrack(0, [])
    return results

# 示例调用
print(subsetsWithDup([1,2,2]))  # 输出: [[], [1], [1,2], [1,2,2], [2], [2,2]]
算法分析
  • 时间复杂度:(O(2^n * n)),其中 (n) 是数组长度。每个元素有选择和不选择两种状态,因此时间复杂度为指数级。每次添加子集到结果中的时间复杂度为 (O(n))。
  • 空间复杂度:(O(n)),递归栈的深度最多为 (n)。

方法二:迭代法

解题步骤
  1. 迭代构建:从空集开始,每次迭代添加一个新元素到所有已存在的子集中,形成新的子集,并注意处理重复元素。
完整的规范代码
def subsetsWithDup(nums):
    """
    使用迭代法生成所有可能的子集,处理重复元素
    :param nums: List[int], 输入的整数数组
    :return: List[List[int]], 所有可能的子集
    """
    nums.sort()
    results = [[]]
    start, end = 0, 0
    for i in range(len(nums)):
        start = 0
        # 如果当前数字和前一个数字相同,则只在上一轮新加入的子集基础上追加
        if i > 0 and nums[i] == nums[i-1]:
            start = end + 1
        end = len(results) - 1
        for j in range(start, len(results)):
            results.append(results[j] + [nums[i]])
    return results

# 示例调用
print(subsetsWithDup([1,2,2]))  # 输出: [[], [1], [1,2], [1,2,2], [2], [2,2]]
算法分析
  • 时间复杂度:(O(2^n * n)),每个元素可能会导致结果翻倍,需要遍历并复制现有的所有子集。
  • 空间复杂度:(O(2^n)),存储所有的子集。

方法三:位掩码法

解题步骤
  1. 位掩码生成:利用位掩码的方法生成所有可能的组合。
  2. 去重处理:对于生成的每个组合,检查是否是重复的,若不是则添加到结果集中。
完整的规范代码
def subsetsWithDup(nums):
    """
    使用位掩码法生成所有可能的子集,并处理重复元素
    :param nums: List[int], 输入的整数数组
    :return: List[List[int]], 所有可能的子集
    """
    nums.sort()
    results = []
    seen = set()
    n = len(nums)
    for i in range(1 << n):  # 从 0 到 2^n - 1
        subset = []
        for j in range(n):
            if i & (1 << j):  # 检查第 j 位是否为 1
                subset.append(nums[j])
        # 转换成元组检查是否重复
        subset_tuple = tuple(subset)
        if subset_tuple not in seen:
            seen.add(subset_tuple)
            results.append(subset)
    return results

# 示例调用
print(subsetsWithDup([1,2,2]))  # 输出: [[], [1], [1,2], [1,2,2], [2], [2,2]]
算法分析
  • 时间复杂度:(O(2^n * n)),位掩码方法生成所有可能的子集,并对每个子集进行处理。
  • 空间复杂度:(O(2^n)),用于存储结果和用于查重的集合。

方法四:字典树(Trie)技术

解题步骤
  1. 构建字典树:为数组中的每个元素构建一个字典树,以存储所有可能的子集组合。
  2. 遍历字典树:遍历字典树以生成所有唯一的子集。
完整的规范代码

这个方法在实际应用中比较复杂,通常不推荐用于这种类型的问题,因为它过于复杂,适合处理更具体的、需要快速查找和插入的场景。因此,这里不提供具体代码实现,而是保持理论上的探讨。

方法五:动态规划

解题步骤
  1. 初始化动态表:以空集开始,逐步添加元素。
  2. 处理重复元素:对于重复元素,仅在上一次新增的子集中添加,防止产生重复的子集。
完整的规范代码
def subsetsWithDup(nums):
    """
    动态规划法生成所有可能的子集,并处理重复元素
    :param nums: List[int], 输入的整数数组
    :return: List[List[int]], 所有可能的子集
    """
    nums.sort()
    results = [[]]
    last_count = 0
    for i in range(len(nums)):
        start = last_count if i > 0 and nums[i] == nums[i-1] else 0
        last_count = len(results)
        results += [r + [nums[i]] for r in results[start:]]

    return results

# 示例调用
print(subsetsWithDup([1,2,2]))  # 输出: [[], [1], [1,2], [1,2,2], [2], [2,2]]
算法分析
  • 时间复杂度:(O(2^n)),每次迭代都会根据当前结果数量添加新的子集。
  • 空间复杂度:(O(2^n)),存储所有生成的子集。

不同算法的优劣势对比

特征方法一:回溯法方法二:迭代法方法三:位掩码法方法四:字典树技术方法五:动态规划
时间复杂度(O(2^n * n))(O(2^n * n))(O(2^n * n))高于 (O(2^n))(O(2^n))
空间复杂度(O(n))(O(2^n))(O(2^n))可能非常高(O(2^n))
优势直观,易于理解简单易实现高效,直接高效查找和插入高效,易于实现
劣势可能栈溢出结果存储消耗大需要额外处理重复过于复杂需要处理重复元素

应用示例

这些方法在处理涉及到组合生成的问题时非常有用,例如在权限管理系统中生成角色的权限组合、在统计学中用于数据分析的各种组合情况生成等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年【G3锅炉水处理】试题及解析及G3锅炉水处理模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年G3锅炉水处理试题及解析为正在备考G3锅炉水处理操作证的学员准备的理论考试专题&#xff0c;每个月更新的G3锅炉水处理模拟考试题祝您顺利通过G3锅炉水处理考试。 1、【多选题】在可逆反应中&#xff0c;下面哪…

Node.js -- express 框架

文章目录 1. express 使用2. 路由2.1 路由的使用2.2 获取请求报文参数2.3 获取路由参数2.4 路由参数练习 3. express 响应设置4. 中间件4.1 全局中间件4.2 路由中间件4.3 静态资源中间件 5. 获取请求体数据 body-parser6. 防盗链7. 路由模块化8. 模板引擎8.1 了解EJS8.2 列表渲…

面试二十四、继承多态

一、继承的本质和原理 组合&#xff08;Composition&#xff09;&#xff1a; 组合是一种"有一个"的关系&#xff0c;表示一个类包含另一个类的对象作为其成员。这意味着一个类的对象包含另一个类的对象作为其一部分。组合关系通常表示强关联&#xff0c;被包含的对象…

【Week-Y7】使用自己的数据集训练YOLO-v8

文章目录 一、官方环境配置与测试1. 配置环境2. 用官方图片测试&#xff08;图片下载失败&#xff09;3. 用本地图片测试&#xff0c;检查配置的环境是否可用 二、使用自己的数据集进行训练测试1. 执行split_train_val.py文件2. 执行python .\voc_label.py文件3. 创建fruit.yam…

[Python基础知识]05函数和模块

一、函数的定义 格式&#xff1a;def 函数名&#xff08;参数列表&#xff09;: 注&#xff1a; 函数代码块以 def 关键词开头&#xff0c;后接函数标识符名称和圆括号()。即使该函数不需要接收任何参数&#xff0c;也必须保留一对空的圆括号 函数形参不需要声明其类型&#x…

layui中禁用div标签等操作

为了实现点击表格行后触发事件 然后去触发后进行操作 页面流程操作设置规定 不可编辑直接添加属性 class"layui-disabled"如果在最大的 div 设置不可编辑 但是内部有些还是可以触发使用的 所以就重写一下 取到当前 div 下的 所有的子元素 然后在给所有的子元素…

闲话 ASP.NET Core 数据校验(二):FluentValidation 基本用法

前言 除了使用 ASP.NET Core 内置框架来校验数据&#xff0c;事实上&#xff0c;通过很多第三方框架校验数据&#xff0c;更具优势。 比如 FluentValidation&#xff0c;FluentValidation 是第三方的数据校验框架&#xff0c;具有许多优势&#xff0c;是开发人员首选的数据校验…

抢先体验:MacOS成功安装PHP8.4教程

根据官方消息&#xff0c;PHP 8.4将于2024年11月21日发布。它将通过三个 alpha 版本、三个 beta 版本和六个候选版本进行测试。 这次的重大更新将为PHP带来许多优化和强大的功能。我们很高兴能够引导您完成最有趣的更新升级&#xff0c;这些更改将使我们能够编写更好的代码并构…

解决React报错Encountered two children with the same key

当我们从map()方法返回的两个或两个以上的元素具有相同的key属性时&#xff0c;会产生"Encountered two children with the same key"错误。为了解决该错误&#xff0c;为每个元素的key属性提供独一无二的值&#xff0c;或者使用索引参数。 这里有个例子来展示错误是…

YOLOv8主要命令讲解

YOLOv8主要有三个常用命令&#xff0c;分别是&#xff1a;train&#xff08;训练&#xff09;、predict&#xff08;预测&#xff09;、export&#xff08;转化模型格式&#xff09;&#xff0c;下面我将展开讲讲三个常用命令的常用参数与具体使用方法。 一、训练 通过自己标…

STM32单片机通过串口控制DDSM210 直驱伺服电机

1 电机介绍 官方资料&#xff1a;https://www.waveshare.net/wiki/DDSM210 DDSM210 直驱伺服电机是基于一体化开发理念&#xff0c;集外转子无刷电机、编码器、伺服驱动于一体的高可靠性永磁同步电动机&#xff0c;其结构紧凑&#xff0c;安装方便&#xff0c;运行稳定&#x…

react核心知识

1. 对 React 的理解、特性 React 是靠数据驱动视图改变的一种框架&#xff0c;它的核心驱动方法就是用其提供的 setState 方法设置 state 中的数据从而驱动存放在内存中的虚拟 DOM 树的更新 更新方法就是通过 React 的 Diff 算法比较旧虚拟 DOM 树和新虚拟 DOM 树之间的 Chan…

【PCL】教程 supervoxel_clustering执行超体聚类并可视化点云数据及其聚类结果

[done, 417.125 ms : 307200 points] Available dimensions: x y z rgba 源点云milk_cartoon_all_small_clorox.pcd > Loading point cloud... > Extracting supervoxels! Found 423 supervoxels > Getting supervoxel adjacency 这段代码主要是使用PCL&#xff08;Po…

Linux进程——进程的创建(fork的原理)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经会使用getpid/getppid函数来查看pid和ppid,本篇文章会介绍第二种查看进程的方法&#xff0c;以及如何创建子进程&#xff01; 本篇主要内容&#xff1a; 查看进程的第二种方法创建子进程系统调用函数fork 在开始前&#xff…

【华为】路由综合实验(基础)

【华为】路由综合实验 实验需求拓扑配置AR1AR2AR3AR4AR5PC1PC2 查看通信OSPF邻居OSPF路由表 BGPBGP邻居BGP 路由表 配置文档 实验需求 ① 自行规划IP地址 ② 在区域1里面 启用OSPF ③ 在区域1和区域2 启用BGP&#xff0c;使AR4和AR3成为eBGP&#xff0c;AR4和AR5成为iBGP对等体…

buuctf-misc-22.神秘龙卷风1

22.神秘龙卷风1 题目&#xff1a;暴力破解-翻译Brainfuck计算机语言 根据提示是4位密码&#xff0c;直接破解密码即可 解压后发现是这样一个文档 我们尝试使用网站翻译这个 内容由“”、“.”、“>”三种符号组成&#xff0c;我刚开始认为这是一种密文&#xff0c;经过搜索…

thinkpad电脑文件隐藏了怎么恢复?教你几招

在使用ThinkPad电脑时&#xff0c;有时我们可能会发现一些文件或文件夹突然“消失”了&#xff0c;这通常是因为它们被隐藏了。本文将为您介绍几招恢复ThinkPad电脑上隐藏文件的方法&#xff0c;帮助您轻松找回丢失的文件。 图片来源于网络&#xff0c;如有侵权请告知 一、了解…

【实时数仓架构】方法论

笔者不是专业的实时数仓架构&#xff0c;这是笔者从其他人经验和网上资料整理而来&#xff0c;仅供参考。写此文章意义&#xff0c;加深对实时数仓理解。 一、实时数仓架构技术演进 1.1 四种架构演进 1&#xff09;离线大数据架构 一种批处理离线数据分析架构&#xff0c;…

when to create a ViewRootImpl

when to create a ViewRootImpl when method setView is called: when method dispatchDetachedFromWindow is called:

预训练模型介绍

一、什么是GPT GPT 是由人工智能研究实验室 OpenAI 在2022年11月30日发布的全新聊天机器人模型, 一款人工智能技术驱动的自然语言处理工具 它能够通过学习和理解人类的语言来进行对话, 还能根据聊天的上下文进行互动,能完成撰写邮件、视频脚本、文案、翻译、代码等任务 二、 为…
最新文章