321. 拼接最大数

1. 题目

321. 拼接最大数

2. 解题思路

题目精简一下:
给你两个数组,从每个数组选取N个元素(需要保持相对顺序,比如从数组[4,8,2]选取两个元素,选取出来后必须保持顺序,比如选4和2,那么组成新数组这两个元素的顺序必须还是4在2前面),元素总长度不超过K,组成一个最大的数组。

核心思路如下:
从两个数组分别选取不同长度的子序列,进行merge后再进行比较。那么可以拆分为几个步骤:
1、从数组1选取N个元素,数组2选取K-N个元素,分别组成两个子序列
2、从两个数组组成对应的子序列,使用单调栈思想(遍历数组,如果当前数字比已选择的最后一个数字大,并且还可以替换元素,则删除已选的元素并选取当前更大的元素。),选出数组中最大的子序列,然后进行合并即可
所以可以知道,我们需要几个核心方法

  • 从传入的数组中选取特定长度的最大子序列
  • 合并子序列为一个完整数组
  • 判断来比较两个数组(或者两个数组的剩余部分)哪个“更大”

3. 代码

3.1. 注意事项

1、首先来看下这段代码
image.png

[!NOTE] 其中的i<=m,k-i<=n为什么能取到等号
众所周知,我们平常在遍历数组的时候一般都是0~length-1这样就是一个完整的范围,那这里为什么能取到等号呢?
首先要明白我们这个循环的目的是为了什么,它是为了从数组中选取N个元素。

  • nums1 中最多选择 m 个元素,也就是数组 nums1 的所有元素。
  • i = m 时,表示你已经选择了 nums1 的所有元素,而此时从 nums2 中选择 k - i 个元素。
  • 所以,i 取到 m 是合理的。

  • nums2 中最多选择 n 个元素,也就是数组 nums2 的所有元素。
  • k - i = n 时,表示你已经选择了 nums2 的所有元素,而此时从 nums1 中选择 i = k - n 个元素。
  • 所以,k - i 取到 n 也是合理的。

2、看findMaxNumber中的这段代码
image.png

[!NOTE] Title
它的核心逻辑就是看当前选择的元素是不是比现在的元素小,如果比现在的元素小而且还有可替换的元素,那么用当前元素替换已选择元素。
其中的canReplace就是关键,最开始它的值是nums.length - len代表在选取 len 个元素后,尚未选中的元素数量,它们可以被用来替换当前已选中的元素,达到优化结果的目的。
在当前元素小于已选取的上个元素的时候,canReplace--,这是因为这个元素被跳过了,那么也就不在我们可替换的列表中了,所以canReplace需要减少1

[!NOTE] 为什么进行替换的时候要用while不用if

  • if 语句:只能进行一次条件判断,不适合处理需要删除多个元素的情况,因此会错过更优的选择。
  • while 循环:能够处理连续的删除操作,以确保最终得到的子序列是最大的。

请看下面的例子:
数组为{2, 9, 5, 4, 8, 3} len=3。正确答案应该是[9,8,3]
首先来看if情况下
image.png
最终得到答案[9,5,8]是错误的
我们再来看while情况下:
image.png

实在没办法理解可以把代码粘贴到IDEA自己断点就能看出来了:

public class Test {  public static void main(String[] args) {  int[] nums = {2, 9, 5, 4, 8, 3};  int k = 3;  int[] res = findMaxNumber(nums, k);  for (int i : res) {  System.out.println(i);  }  }  public static int[] findMaxNumber(int[] nums, int len) {  int[] res = new int[len];  //已经选择了的元素个数  int alreadyChoose = 0;  //还能替换的元素个数  int canReplace = nums.length - len;  // 遍历整个数组进行优选  for (int i = 0; i < nums.length; i++) {  while (alreadyChoose > 0 && res[alreadyChoose - 1] < nums[i] && canReplace > 0) {  // 回退alreadyChoose,达到替换值的效果  alreadyChoose--;  canReplace--;  }  if (alreadyChoose < len) {  res[alreadyChoose] = nums[i];  alreadyChoose++;  } else {  // 如果跳过当前元素,那么可替换的元素就减少一个  canReplace--;  }  }  return res;  }  
}

3.2. 完整代码

class Solution {public int[] maxNumber(int[] nums1, int[] nums2, int k) {int m = nums1.length;int n = nums2.length;int[] res = new int[0];// 找到两个数组中选取x个元素的时候的最大子序列for (int i = 0; i <= k && i <= m; i++) {if (k - i >= 0 && k - i <= n) {// 找到两个最大值的序列int[] subNumber1 = findMaxNumber(nums1, i);int[] subNumber2 = findMaxNumber(nums2, k - i);int[] tmp = merge(subNumber1, subNumber2);if (compare(tmp, 0, res, 0)) {res = tmp;}}}return res;}private int[] findMaxNumber(int[] nums, int len) {int[] res = new int[len];//已经选择了的元素个数int alreadyChoose = 0;//还能替换的元素个数int canReplace = nums.length - len;// 遍历整个数组进行优选for (int i = 0; i < nums.length; i++) {while (alreadyChoose > 0 && res[alreadyChoose - 1] < nums[i] && canReplace > 0) {// 回退alreadyChoose,达到替换值的效果alreadyChoose--;canReplace--;}if (alreadyChoose < len) {res[alreadyChoose] = nums[i];alreadyChoose++;} else {// 如果跳过当前元素,那么可替换的元素就减少一个canReplace--;}}return res;}private int[] merge(int[] nums1, int[] nums2) {int[] res = new int[nums1.length + nums2.length];int cur = 0;int p1 = 0;int p2 = 0;while (cur < nums1.length + nums2.length) {// 对比下来NUM1的当前元素大于nums2if (compare(nums1, p1, nums2, p2)) {res[cur++] = nums1[p1++];} else {res[cur++] = nums2[p2++];}}return res;}/*** compare 函数用来比较两个数组(或者两个数组的剩余部分)哪个“更大”。* 返回true代表num1大,否则代表nums2大*/private boolean compare(int[] nums1, int p1, int[] nums2, int p2) {// nums2 用完了,nums1 更大(只能选nums1了)if (p2 >= nums2.length) {return true;}// nums1 用完了,nums2 更大(只能选nums2了)if (p1 >= nums1.length) {return false;}// nums1 当前元素大,nums1 更大if (nums1[p1] > nums2[p2]) {return true;}// nums2 当前元素大,nums2 更大if (nums1[p1] < nums2[p2]) {return false;}// 如果当前元素相等,递归比较后续的元素return compare(nums1, p1 + 1, nums2, p2 + 1);}
}

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

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

相关文章

对操作系统(OS)管理和进程的理解

文章目录 从冯诺依曼体系入手来了解计算机硬件部分操作系统操作系统的概念设计操作系统&#xff08;OS&#xff09;的目的对下&#xff08;硬件&#xff09;OS的管理对上如何理解系统调用 进程 在计算机系统中&#xff0c;硬件、操作系统和进程是三个至关重要的概念。它们相互协…

C# 反射之动态生成dll/exe

这个可能应该属于反射的高级使用范围了&#xff0c;平常在项目中使用的人估计也不是很多。由于使用反射的话会降低性能&#xff0c;比如之前用到的GetValue、SetValue等之类&#xff0c;但是使用这种方式会大大提高效率&#xff0c;在这里我只想说&#xff0c;都直接写IL指令了…

C++八股文之面向对象篇

&#x1f916;个人主页&#xff1a;晚风相伴-CSDN博客 思维导图链接&#xff1a;面向对象的性质 持续更新中…… &#x1f496;如果觉得内容对你有帮助的话&#xff0c;还请给博主一键三连&#xff08;点赞&#x1f49c;、收藏&#x1f9e1;、关注&#x1f49a;&#xff09;吧 …

【CSS in Depth 2 精译_031】5.3 Grid 网格布局的两种替代语法

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

【VSCode】VSCode Background 背景插件辅助窗口程序

前排贴上Github项目链接 GitHub窗口项目链接 这是一个基于VSCode上由shalldie上传的background扩展制作的windows窗口程序。 该程序旨在通过窗口程序尽可能的完善该扩展原有的功能。 background - shalldie 的最大优势是我目前仅在其扩展上发现了UseFront的选项&#xff0c;这…

2011年全国硕士研究生入学统一考试计算机科学与技术

1. 试卷背景&#xff1a; 试题&#xff1a;2011年全国硕士研究生入学统一考试计算机科学与技术学科联考中的计算机学科专业基础综合试题。难点&#xff1a;该问题的研究难点在于试题涵盖了计算机科学与技术的多个方面&#xff0c;包括数据结构、算法、计算机组成原理、操作系统…

text2sql(NL2Sql)综述《The Dawn of Natural Language to SQL: Are We Fully Ready?》

《The Dawn of Natural Language to SQL: Are We Fully Ready?》(github)出自2024年6月的NL2SQL(Natural language to SQL )综述论文。这篇论文尝试回答如下三个问题&#xff1a; 问题1:NL2SQL的现状是什么&#xff1f;(Q1:Where Are we Now?) 论文图1总结了近20年NL2SQL方法…

Qt:懒汉单例(附带单例使用和内存管理)

前言 本文主要写懒汉单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。 正文 以下是两种懒汉单例的写法 1. 懒汉式单例&#xff08;多线程不安全&#xff0c;但是在单线程里面是安全的&…

protobuf中c、c++、python使用

文章目录 protobuf实例&#xff1a;例题1&#xff1a;[CISCN 2023 初赛]StrangeTalkBot分析&#xff1a;思路&#xff1a;利用&#xff1a; 例题2&#xff1a;[CISCN 2024]protoverflow分析&#xff1a; protobuf Protocol Buffers&#xff0c;是Google公司开发的一种数据描述语…

二十三种设计模式之原型模式

一.什么是原型模式 ‌‌原型模式是一种创建型对象设计模式&#xff0c;它通过复制一个已经创建的实例&#xff08;即原型对象&#xff09;来创建一个和原型对象相同的新对象。‌ 这种模式在面向对象软件设计中非常有用&#xff0c;因为它允许通过复制现有对象来快速生成多个相似…

新160个crackme - 057-bbbs-crackme04

运行分析 因软件版本老旧&#xff0c;需使用windows XP虚拟机运行有个SystemID&#xff0c;值为12345678需破解User ID和Password PE分析 yC壳&#xff0c;32位 OD手动脱壳 使用windows XP虚拟机&#xff0c;将程序拖入OD按一下F8&#xff0c;ESP变红&#xff0c;根据ESP定律设…

子比主题美化 - 可移动悬浮窗 弹窗功能代码教程

移动页面演示效果 这个功能完全适配子比主题使用&#xff0c;代码开源&#xff0c;可以做其它功能弹窗或者菜单栏等等&#xff0c;后期有时间在做成桌面页面也可以鼠标移动&#xff0c;点击参考&#xff1a;移动悬浮窗详细代码教程

黑马十天精通MySQL知识点

一. MySQL概述 安装使用 MySQL安装完成之后&#xff0c;在系统启动时&#xff0c;会自动启动MySQL服务&#xff0c;无需手动启动。 也可以手动的通过指令启动停止&#xff0c;以管理员身份运行cmd&#xff0c;进入命令行执行如下指令&#xff1a; 1 、 net start mysql80…

SpringBoot父子工程搭建

SpringBoot父子工程搭建 1、父工程 1.1、创建父工程 1.2、移除无用文件 1.3、修改pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XML…

秋韵虫趣.

文章目录 虫鸣概览虫坛文化蟀种纷呈中华蟋蟀宁阳蟋蟀刻点铁蟋长颚斗蟋 油葫芦棺头蟋中华灶蟋小素蟋树皮蟋蟀 花生大蟋斑腿针蟋其他鸣虫树蟋&#xff0c;又名竹蛉、邯郸梨片蟋&#xff0c;又名金钟、天蛉、绿蛣蛉、银琵琶凯纳奥蟋&#xff0c;又名石蛉&#xff0c;鳞蟋黄蛉蟋&am…

NarratoAI利用AI大模型,一键解说并剪辑视频

测试视频: 字幕/配乐后期添加的,视频由NarratoAI自动生成的 雪迷宫-NarratoAI利用AI大模型剪辑解说视频测试 WIN整合包 下载链接&#xff1a;https://pan.quark.cn/s/8f54ef99e3fb 使用前先更新&#xff0c;运行update.bat Gemini API Key 访问 https://aistudio.google.c…

quartz 搭配SQL Server时出现deadlock的解决方案

背景&#xff1a; 最近在折腾换OA系统&#xff0c;遇到了一个很诡异的事情。在测试阶段&#xff0c;OA系统经常莫名地宕机&#xff0c;停止响应。查下来&#xff0c;发现是数据库出现大量死锁&#xff0c;耗尽了连接池。出现问题的语句是一样的&#xff0c;问题锁定在QRTZ_TRI…

C++ 面试必备知识大全:从基础到高级特性全面解析

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; C 面试中常见的问题涵盖了语言基础、面向对象编程、内存管理、STL&#xff08;标准模板库&#xff09;、并发编程、设计模式等。以下是一些常见的 C 面试问题及其详细答案总结&#xff1…

第311题| 超好用!二重积分求旋转体体积公式|武忠祥老师每日一题

第一步&#xff1a; &#xff08;1&#xff09;找渐近线&#xff0c;先看水平渐近线&#xff0c;看x趋于无穷时&#xff0c;y有没有趋于一个有限的值。 , 得出水平渐近线y1。因为左右两边都是水平渐近线&#xff0c;所以没有斜渐近线。 第二步&#xff1a; 画出图像&#…

e选择排序---复杂度O(X^2)

排序原理: 1.每一次遍历的过程中&#xff0c;都假定第一个索引处的元素是最小值,和其他索引处的值依次进行比较,如果当前索引处的值大于其他某个素引处的值&#xff0c;则假定其他某个索引出的值为最小值&#xff0c;最后可以找到最小值所在的索引 2.交换第一个索引处和最小值所…