LeetCode-2007. 从双倍数组中还原原数组【贪心 数组 哈希表 排序】

news2025/1/18 7:17:37

LeetCode-2007. 从双倍数组中还原原数组【贪心 数组 哈希表 排序】

  • 题目描述:
  • 解题思路一:排序 + 哈希表
  • 解题思路二:排序 + 队列
  • 解题思路三:消消乐

题目描述:

一个整数数组 original 可以转变成一个 双倍 数组 changed ,转变方式为将 original 中每个元素 值乘以 2 加入数组中,然后将所有元素 随机打乱 。

给你一个数组 changed ,如果 change 是 双倍 数组,那么请你返回 original数组,否则请返回空数组。original 的元素可以以 任意 顺序返回。

示例 1:

输入:changed = [1,3,4,2,6,8]
输出:[1,3,4]
解释:一个可能的 original 数组为 [1,3,4] :

  • 将 1 乘以 2 ,得到 1 * 2 = 2 。
  • 将 3 乘以 2 ,得到 3 * 2 = 6 。
  • 将 4 乘以 2 ,得到 4 * 2 = 8 。
    其他可能的原数组方案为 [4,3,1] 或者 [3,1,4] 。
    示例 2:

输入:changed = [6,3,0,1]
输出:[]
解释:changed 不是一个双倍数组。
示例 3:

输入:changed = [1]
输出:[]
解释:changed 不是一个双倍数组。

提示:

1 <= changed.length <= 105
0 <= changed[i] <= 105

解题思路一:排序 + 哈希表

在这里插入图片描述

class Solution:
    def findOriginalArray(self, changed: List[int]) -> List[int]:
        changed.sort()
        ans = []
        cnt = Counter()
        for x in changed:
            if x not in cnt:  # x 不是双倍后的元素
                cnt[x * 2] += 1 # 标记一个双倍元素
                ans.append(x)
            else: # x 是双倍后的元素
                cnt[x] -= 1 # 清除一个标记
                if cnt[x] == 0:
                    del cnt[x]
        # 只有所有双倍标记都被清除掉,才能说明 changed 是一个双倍数组
        return [] if cnt else ans

时间复杂度:O(nlogn)
空间复杂度:O(n)

解题思路二:排序 + 队列

在方法一中,我们是小到大遍历 x=changed[i]的,所以加到哈希表中的 2x(双倍标记)也是从小到大的,并且最先加到哈希表中的双倍标记,也会最先清除掉。这种「先进先出」的性质启发我们把哈希表替换成更轻量的队列,队首就是下一个等待被清除的双倍标记。

具体来说,在循环中:

  1. 如果队列为空,把 x 加入答案,把 2x 加入队尾。如果后面遍历到一个等于 2x 的元素,则说明 x 和 2x 都在数组中,配对成功。
  2. 如果队列不为空,并且队首小于 x,由于后面遍历到的数只会更大,所以队首无法配对,返回空数组。
  3. 如果队列不为空,并且队首等于 x,配对成功,弹出队首。
  4. 如果队列不为空,并且队首大于 x,把 x 加入答案,把 2x 加入队尾。
class Solution:
    def findOriginalArray(self, changed: List[int]) -> List[int]:
        changed.sort()
        ans = []
        q = deque()
        for x in changed:
            if q:
                if q[0] < x:  # 无法配对
                    return []
                if q[0] == x:  # 配对成功
                    q.popleft()  # 清除一个标记
                    continue
            ans.append(x)
            q.append(x * 2)  # 添加双倍标记
        # 只有所有双倍标记都被清除掉,才能说明 changed 是一个双倍数组
        return [] if q else ans

时间复杂度:O(nlogn)
空间复杂度:O(n)

解题思路三:消消乐

在这里插入图片描述

在给定的代码中,pop(0, 0)是一种使用Counter对象的方法。Counter是Python中的一个内置类,用于计数可哈希对象(例如列表、元组、字符串等)中元素的出现次数。

让我们分解这个代码片段:

cnt = Counter(changed): 这一行创建了一个Counter对象cnt,并使用changed中的元素对其进行初始化。这意味着cnt对象将会统计changed中每个元素的出现次数。
cnt0 = cnt.pop(0, 0): 这一行调用了cnt对象的pop方法,并传递了两个参数。pop方法用于从Counter对象中移除并返回指定键的元素,如果键不存在,则返回指定的默认值。具体来说:

  • 第一个参数0是要移除的键,即从cnt中移除键为0的元素。
  • 第二个参数0是默认值,表示如果键不存在,则返回0。

因此,pop(0, 0)这个操作的意思是从cnt中移除键为0的元素,如果键不存在,则返回0。

class Solution:
    def findOriginalArray(self, changed: List[int]) -> List[int]:
        cnt = Counter(changed)
        # 单独处理 0
        cnt0 = cnt.pop(0, 0)
        print(cnt0)
        if cnt0 % 2:
            return []
        ans = [0] * (cnt0 // 2)

        done = set()
        for x in cnt:
            # 如果 x 已处理完毕,或者 x/2 在 cnt 中,则跳过
            if x in done or x % 2 == 0 and x // 2 in cnt:
                continue
            # 把 x, 2x, 4x, 8x, ... 全部配对
            while x in cnt:
                # 每次循环,把 cnt_x 个 x 和 cnt_x 个 2x 配对
                cnt_x = cnt[x]
                # 无法配对,至少要有 cnt_x 个 2x
                if cnt_x > cnt[x * 2]:
                    return []
                ans.extend([x] * cnt_x)
                # x 配对完成
                done.add(x)
                if cnt_x < cnt[x * 2]:
                    # 还剩下一些 2x
                    cnt[x * 2] -= cnt_x
                    x *= 2
                else:
                    # 2x 配对完成
                    done.add(x * 2)
                    x *= 4
        return ans

时间复杂度:O(n)
空间复杂度:O(n)

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

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

相关文章

使用Spring 完成转账业务添加日志功能

(完整的代码在文章附带文件中 , 文章里的代码仅作展示 , 可能有部分不完善 代码地址 :下载:https://javazhang.lanzn.com/i5oLI1vyiile 密码:1234 ) 任务目标 具体实现方法和心得 步骤1. 导入依赖项Spring依赖 , aop依赖,德鲁伊依赖,mybatis依赖 , mysql驱动 , mybatis-sprin…

jar包做成Windows Service 服务,不能访问网络映射磁盘

在Windows操作系统中&#xff0c;系统服务&#xff08;Services&#xff09;、计划任务&#xff08;Scheduled Tasks&#xff09;以及很多系统调用都是以SYSTEM系统账号进行操作的。用 net use 挂载&#xff0c;或者在文件管理器上直接挂载&#xff0c;挂载卷是以 Administrato…

在 ingress-nginx 负载均衡器上阻止特定路径

背景&#xff1a; 安全临时通知生产环境swagger的路径没屏蔽&#xff0c;正常思路是通过以下配置才能起作用&#xff0c;但是重启才能生效&#xff0c;又会影响用户使用。 springfox: documentation: # 总开关&#xff08;同时设置auto-startupfalse&#xff0c;否则/v3…

2020年海南职业院校技能大赛高职组

2020年海南职业院校技能大赛高职组“信息安全管理与评估”赛项任务书 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu5488233 赛项时间…

go版本1.16.5 运行项目出现undefined: math.MaxInt报错

问题描述 go版本 go1.16.5 项目引用了 包go-sqlite3 v1.14.17 github.com/mattn/go-sqlite3 v1.14.17运行报错 # github.com/mattn/go-sqlite3 D:\GoPATH\pkg\mod\github.com\mattn\go-sqlite3v1.14.17\sqlite3_opt_serialize.go:41:26: undefined: math.MaxInt原因分析&…

华为 2024 届实习校园招聘-硬件通⽤/单板开发——第八套

华为 2024 届实习校园招聘-硬件通⽤/单板开发——第八套 部分题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共十套&#xff09;获取&#xff08;WX:didadidadidida313&#xff0c…

理解相似性搜索(也称为语义搜索)的指南

了解人工智能相似性搜索 理解相似性搜索&#xff08;也称为语义搜索&#xff09;的指南&#xff0c;这是人工智能最新阶段的关键发现之一。 目录 一、说明二、向量三、人工智能中的向量四、将文本转换为向量五、创建向量嵌入六、存储向量嵌入七、相似性搜索八、执行相似性搜索…

OpenCV添加文字和水印------c++

添加文字 bool opencvTool::addText(cv::Mat& image, const std::string text, const cv::Point& position, double fontScale, cv::Scalar color, int thickness, int fontFace) {cv::putText(image, text, position, fontFace, fontScale, color, thickness);return…

3DTiles生产流程与规范

一篇19年整理的比较老的笔记了。更多精彩内容尽在数字孪生平台。 瓦片切分 标准的四叉树切分对于均匀分布的地理数据切片非常有效&#xff0c;但是这样均等的切分不适用于随机分布、不均匀分布的地理数据&#xff0c;当地理数据稀疏分布的时候&#xff0c;均等的四叉树就不再高…

Linux配置腾讯云yum源(保姆级教学)

1. 备份原有的 yum 源配置文件 例如&#xff1a; mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2. 下载腾讯云的 yum 源配置文件 例如&#xff1a; wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/…

【1429】招生管理管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 招生管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

共享单车(二):项目日志

stdin, stdout, stderr Linux系统下&#xff0c;当一个用户进程被创建时&#xff0c;与之对应的三个数据流&#xff08;stdin&#xff0c;stdout和stderr&#xff0c;即三个文件&#xff09;也会被创建。 stdin&#xff0c;标准输入文件&#xff0c;通常对应着终端的键盘。 s…

Docker网络及CPU资源控制

一、实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容…

JVM常见的垃圾回收器

1、回收方法区&#xff1a; 方法区回收价值很低&#xff0c;主要回收废弃的常量和无用的类。 方法区中的存储&#xff1a; 方法区中存储的是加载的类的信息&#xff0c;常量&#xff0c;静态变量&#xff0c;即时编译后的代码等数据&#xff0c;所以回收的对象也就是这些内…

Qt笔记-解决子控制大小获取不正确(width和height)需要重制窗体后,才能获得正确的值

在Qt中&#xff0c;子控件的宽度和高度在构造后并不准确&#xff0c;而只有在调整窗口大小后才正确&#xff0c;这可能是因为子控件的布局或者约束尚未完全计算和应用。 为了解决这个问题&#xff0c;可以使用QTimer来延迟获取子控件的宽度和高度&#xff0c;以确保在布局和约…

Footprint Analytics 与 GalaChain 达成战略合作

​ Footprint Analytics 宣布与 GalaChain 达成战略合作。GalaChain 是 Gala 旗下的 Layer 1 区块链。此次合作标志着双方在游戏&#xff08;包括 Gala Games) 、娱乐和金融等多个行业的区块链生态系统革新方面迈出了重要的一步。 GalaChain 致力于满足企业级项目的广泛需求&…

【网安小白成长之路】8.sql注入操作

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

基于ssm微信小程序的4S店客户管理系统

采用技术 基于ssm微信小程序的4S店客户管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 管理员端 管理员登录 管理员首页 用户管理 门店管理 …

Java技术学习|消息队列|初级RabbitMQ

学习材料声明 黑马RabbitMQ快速入门教程&#xff0c;快速掌握rabbitmq、springAMQP消息中间件 是非常初级的学习&#xff0c;听说后续的高级课程会涉及到微服务之类的&#xff0c;所以等学完微服务再回来学。还有redis的高级部分也涉及了微服务&#xff0c;所以也都暂时停止学…

Pick-a-Pic:An open dataset of user preferences for text-to-image generation

1.introduction 1.创建了一个 数据集,每个示例包括一个提示,两个生成的图像以及一个指向首选图像的标签,或者在没有一个图像明显优于另一个时标记为平局。由真实用户创建,包括50w个示例。 2.利用真实用户偏好,训练一个评分函数,使用人类偏好数据和类似于instructGPT奖励…