Python算法例19 创建最大数

news2024/9/21 0:29:19

1. 问题描述

给定两个长度分别是m和n的数组,数组的每个元素都是数字0~9,从这两个数组当中选出k个数字来创建一个最大数,其中k满足k<=m+n,选出来的数字在创建最大数里的位置必须与在原数组内的相对位置一致。返回k个元素的整数数组,尽可能优化算法的时间复杂度和空间复杂度。

2. 问题示例

给出nums1=[3,4,6,5],nums2=[9,1,2,5,8,3],k=5,返回[9,8,6,5,3];给出nums1=[6,7],nums2=[6,0,4],k=5,返回[6,7,6,0,4];给出nums1=[3,9],nums2=[8,9],k=3,返回[9,8,9]。

3. 代码实现

使用贪心算法来解决。具体来说,我们可以固定从nums1中选取多少个数字,然后从nums2中选取剩余的数字,使得它们合起来构成一个长度为k的最大数。

为了实现这个算法,我们需要确定以下步骤:

  1. 实现一个函数,将一个数组中的元素重排,使得它们构成的数字最大;
  2. 对于一个给定的数组nums和整数k,我们需要找到由nums中的数字组成的长度为k的最大数;
  3. 给定两个数组nums1和nums2以及整数k,我们需要找到由nums1和nums2中的数字组成的长度为k的最大数。
def maxNumber(nums1, nums2, k):
    # 重排数组中的元素,使得它们构成的数字最大
    def merge(A, B):
        return [max(A, B).pop(0) for _ in A+B]
    
    # 找到由nums中的数字组成的长度为k的最大数
    def prepare(nums, k):
        drop = len(nums) - k
        out = []
        for num in nums:
            while drop and out and out[-1] < num:
                out.pop()
                drop -= 1
            out.append(num)
        return out[:k]

    # 找到由nums1和nums2中的数字组成的长度为k的最大数
    def lexicographically_greater(a, i, b, j):
        while i < len(a) and j < len(b) and a[i] == b[j]:
            i += 1
            j += 1
        return j == len(b) or (i < len(a) and a[i] > b[j])

    # 尝试从nums1中选取i个数字,从nums2中选取k-i个数字
    res = []
    for i in range(max(0, k-len(nums2)), min(k, len(nums1))+1):
        candidate = merge(prepare(nums1, i), prepare(nums2, k-i))
        res = max(candidate, res) if res != [] else candidate
    return res
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
result = maxNumber(nums1, nums2, k)
print(result)  # 输出 [9, 8, 6, 5, 3]

其中,函数merge()用于将两个数组合并成一个最大数,函数prepare()用于找到由一个数组中的数字组成的长度为k的最大数,函数lexicographically_greater()用于比较两个数组的字典序大小。具体来说,这个函数的作用是,给定两个数组a和b以及它们的起始下标i和j,如果在i和j之后,a比b字典序更大,则返回True,否则返回False。

在主函数maxNumber()中,我们枚举从nums1中选取的数字的个数i,然后从nums2中选取剩余的数字k-i,将它们合并成一个最大数candidate。最后,我们将所有生成的最大数中的最大者返回即可。这个算法的时间复杂度为O((m+n)^3),空间复杂度为O(m+n)。

采用动态规划的方法。具体来说,我们可以使用两个动态规划数组来保存最大数的信息,以减少重复计算。

def maxNumber(nums1, nums2, k):
    def get_max_subsequence(nums, k):
        stack = []
        pop_count = len(nums) - k
        for num in nums:
            while pop_count and stack and stack[-1] < num:
                stack.pop()
                pop_count -= 1
            stack.append(num)
        return stack[:k]

    def merge(nums1, nums2):
        merged = []
        i, j = 0, 0
        while i < len(nums1) and j < len(nums2):
            if nums1[i:] > nums2[j:]:
                merged.append(nums1[i])
                i += 1
            else:
                merged.append(nums2[j])
                j += 1
        merged.extend(nums1[i:])
        merged.extend(nums2[j:])
        return merged

    result = []
    for i in range(max(0, k-len(nums2)), min(k, len(nums1))+1):
        subsequence1 = get_max_subsequence(nums1, i)
        subsequence2 = get_max_subsequence(nums2, k-i)
        merged = merge(subsequence1, subsequence2)
        result = max(result, merged)
    return result
nums1 = [6,7]
nums2 = [6,0,4]
k = 5
result = maxNumber(nums1, nums2, k)
print(result)

在这个实现中,我们定义了两个辅助函数:get_max_subsequence()和merge()。函数get_max_subsequence()用于从一个数组中获取长度为k的最大子序列,这个函数的实现与之前贪心算法中的prepare()函数相同。函数merge()用于合并两个子序列,这个函数的实现与之前贪心算法中的merge()函数相同。

在主函数maxNumber()中,我们使用动态规划来生成最大数。我们首先枚举从nums1中选取的数字的个数i,然后使用get_max_subsequence()函数分别从nums1和nums2中获取长度为i和k-i的最大子序列。接下来,我们使用merge()函数将这两个子序列合并成一个最大数,并将其与之前的结果比较,保留更大的那个。最后,返回最终的最大数。这个算法的时间复杂度为O((m+n)^2),空间复杂度为O(m+n)。

使用单调栈的思想来减少重复计算。具体来说,我们可以使用两个单调递减栈,分别从nums1和nums2中构建。栈的长度为k,每次入栈时,判断当前元素与栈顶元素的大小关系,如果当前元素更大,则将栈顶元素出栈,直到满足栈的长度要求或者栈为空。然后将当前元素入栈。

def maxNumber(nums1, nums2, k):
    def build_max_stack(nums, k):
        stack = []
        drop_count = len(nums) - k
        for num in nums:
            while drop_count > 0 and stack and stack[-1] < num:
                stack.pop()
                drop_count -= 1
            stack.append(num)
        return stack[:k]

    def merge(nums1, nums2):
        merged = []
        i, j = 0, 0
        while i < len(nums1) and j < len(nums2):
            if nums1[i:] > nums2[j:]:
                merged.append(nums1[i])
                i += 1
            else:
                merged.append(nums2[j])
                j += 1
        merged.extend(nums1[i:])
        merged.extend(nums2[j:])
        return merged

    result = []
    for i in range(max(0, k - len(nums2)), min(k, len(nums1)) + 1):
        subsequence1 = build_max_stack(nums1, i)
        subsequence2 = build_max_stack(nums2, k - i)
        merged = merge(subsequence1, subsequence2)
        result = max(result, merged)
    return result
nums1 = [3,9]
nums2 = [8,9]
k = 3
result = maxNumber(nums1, nums2, k)
print(result)

在这个实现中,我们使用了两个辅助函数:build_max_stack()和merge()。函数build_max_stack()用于构建单调递减栈,获取长度为k的最大子序列。函数merge()用于合并两个子序列。

在主函数maxNumber()中,我们通过枚举从nums1中选取的数字的个数i,分别构建nums1和nums2的单调递减栈,并通过merge()函数将这两个子序列合并成一个最大数。最后,返回最终的最大数。这个算法的时间复杂度为O(m+n+k(m+n)),其中m和n分别是nums1和nums2的长度。

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

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

相关文章

Java第一个程序——Hello,World!

“Hello, world”的由来可以追溯到 The C Programming Language 。在这门编程语言中&#xff0c;它被用作第一个演示程序&#xff0c;向人们展示了在计算机屏幕上输出“Hello world”这行字符串的计算机程序。由于这个演示程序的简洁性和直观性&#xff0c;它成为了许多初学者学…

韩语中的一次多用-柯桥基础韩语学习

1.动词&#xff0c;写 일기를 쓰다 写日记 2.动词&#xff0c;戴&#xff08;帽子&#xff0c;眼镜&#xff0c;口罩&#xff09; 안경을 쓰다 戴眼镜 3.动词&#xff0c;使用&#xff08;材料&#xff0c;道具&#xff0c;手段&#xff09; 세제를 쓰다 使用洗剂 4.动词&am…

Java对接腾讯多人音视频房间回调接口示例

在前面我们已经对接好了腾讯多人音视频房间相关内容&#xff1a;Java对接腾讯多人音视频房间示例 为了完善业务逻辑&#xff0c;我们还需要对接它的一些回调接口 官方文档地址 主要就下面这些 这里因为比较简单直接上代码 里面有些工具类和上一章一样这里就没贴&#xff0c;需要…

机器学习 | 集成学习

团结就是力量&#xff01; Ensemble Learning 兼听则明&#xff0c;偏信则暗。 集成学习既是一种思想也是一类算法&#xff0c;它是建立在其他机器学习的算法之上&#xff0c;研究怎么让不同的算法之间进行协同。 既可以监督学习&#xff0c;也可以无监督学习。 集成学习用机器…

Gemini 1.0:Google推出的全新AI模型,改变生成式人工智能领域的游戏规则!

Gemini 1.0&#xff1a;Google推出的全新AI模型&#xff0c;将改变生成式人工智能领域的游戏规则&#xff01; &#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; IT杂谈 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 …

C/C++与MySQL:多线程、大并发和异步操作的实践

C/C与MySQL&#xff1a;多线程、大并发和异步操作的实践 在前面的文章中&#xff0c;我们介绍了如何使用C/C调用MYSQL API进行基本的数据库操作。然而&#xff0c;在实际应用中&#xff0c;特别是面对大量用户请求和高并发场景时&#xff0c;单线程的数据库操作往往显得力不从…

降本不增“笑”的正确打开方式

引言: 在当前行业形势下&#xff0c;降本增效已经是公认的命题&#xff0c;粗放扩张的时代已经过去&#xff0c;接下来是在从业务到技术都需要精细化管理的时代。但在这个命题下&#xff0c;往往未被提及的一点是用户价值。如果为了降本增效&#xff0c;而牺牲了用户价值&…

GeoTrust SSL证书详细介绍

GeoTrust是著名的证书颁发CA机构DigiCert的品牌。GeoTrustSSL产品在Internet上提供从基本域名验证到扩展验证SSL标准支持的最高级验证的安全性。 GeoTrust OV&#xff08;组织验证&#xff09;证书验证域所有权和组织的存在。在颁发证书之前&#xff0c;会检查该组织在公共数据…

Linux学习(2)——基本命令

目录 1、pwd&#xff08;print work directory&#xff09;: 显示当前路径 2、cd&#xff08;change directory&#xff09; &#xff1a;切换目录 2.1路径的分类 2.1.1 绝对路径&#xff1a;以 根&#xff08;/&#xff09; 开头的路径 2.1.2 相对路径&#xff1a;…

CVE-2023-33246 RocketMQ RCE漏洞

一、RocketMQ简介 RocketMQ是一款纯java、分布式、队列模型的开源消息中间件&#xff0c;主要用于在分布式系统中进行异步消息传递&#xff0c;支持事务消息、顺序消息、批量消息、定时消息、消息回溯等功能。 RocketMQ有四个核心组成部分&#xff1a; NameServer&#xff1…

【UML】第8篇 用例图(3/3)

目录 一、用例的关系 1.1 泛化&#xff08;Generalization&#xff09;关系 1.2 包含&#xff08;include&#xff09;关系 1.3 扩展关系 二、用例表示例 不是非要把电影改成连续剧&#xff0c;给大家播&#xff0c;确实是时间和精力有限。 用例图&#xff0c;虽然简单&…

【Python/网络安全】 Git漏洞之Githack工具基本安装及使用详析

[Python/网络安全] Git漏洞之Githack工具基本安装及使用详析 前言安装步骤工具使用实战总结 前言 Git是一个非常流行的开源分布式版本控制系统&#xff0c;它被广泛用于协同开发和代码管理。许多网站和应用程序都使用Git作为其代码管理系统&#xff0c;并将其部署到生产环境中…

Stable-diffusion-webui本地部署和简要介绍

Stable Diffusion 是一款基于人工智能技术开发的绘画软件&#xff0c;它可以帮助艺术家和设计师快速创建高品质的数字艺术作品。是2022年发布的深度学习文本到图像生成模型。它主要用于根据文本的描述产生详细图像&#xff0c;同时也可以应用于其他任务&#xff0c;如内补绘制、…

WPF Halcon机器视觉和运动控制软件通用框架,插件式开发,开箱即用 仅供学习!

点我下载&#xff0c;仅供个人学习使用 参考easyvision开发&#xff0c;集成几十个软件算子此版本以添加ui设计器。具体功能如上所示&#xff0c;可以自定义变量&#xff0c;写c#脚本&#xff0c;自定义流程&#xff0c;包含了halcon脚本和封装的算子&#xff0c;可自定义ui&a…

交叉熵损失(Cross-Entropy loss)

在处理机器学习或深度学习问题时&#xff0c;损失/成本函数用于在训练期间优化模型。目标几乎总是最小化损失函数。损失越低&#xff0c;模型越好。交叉熵损失是最重要的成本函数。它用于优化分类。对交叉熵的理解取决于对 Softmax 激活函数的理解。 一、softmax激活函数 激活…

手机上怎么合成gif?手机图片合成gif分享

手机上的功能越来越丰富&#xff0c;很多电脑上能制作的东西手机上也能制作。那么当我们想要在手机上制作gif动画的时候要怎么操作呢&#xff1f;非常的简单&#xff0c;使用在线制作动画gif&#xff08;https://www.gif.cn/&#xff09;网站-GIF中文网&#xff0c;手机自带浏览…

分析某款go扫描器之四

一、概述 上文提到实现IP的探测存活以及tcp扫描的实现&#xff0c;这部分来分析实现本机网卡信息获取&#xff0c;以及维护一张mac地址表以及ip扫描端口状态表&#xff0c;同时实现syn扫描功能。 项目来源&#xff1a;https://github.com/XinRoom/go-portScan/blob/main/util…

K8S(十一)—Service详解

目录 Service发布服务&#xff08;服务类型&#xff09;type: ClusterIP选择自己的 IP 地址例子 type: NodePort选择你自己的端口为 type: NodePort 服务自定义 IP 地址配置例子 type: LoadBalancer混合协议类型的负载均衡器禁用负载均衡器节点端口分配设置负载均衡器实现的类别…

互动破千万!冰雪营销两大玩法,小红书数据分析!

2022年冬奥会带火了冰雪运动&#xff0c;到如今“冰雪热”仍在持续。通过千瓜数据&#xff0c;查看小红书平台“冰雪”这一关键词的数据&#xff0c;近30天互动总量超过1300万&#xff0c;官方连续发布的几场活动&#xff0c;皆与冰雪相关&#xff0c;#东北精神上的快乐老家 #追…

js中async和await高级用法

文章目录 一、介绍二、async/await与高阶函数三、控制并发数四、使用async/await优化递归五、异步初始化类实例六、在async函数中使用await链式调用七、结合async/await和事件循环八、使用async/await简化错误处理九、最后 一、介绍 JavaScript的异步编程已经从回调(callback)…