华为OD机考算法题:生日礼物

题目部分

题目生日礼物
难度
题目说明小牛的孩子生日快要到了,他打算给孩子买蛋糕和小礼物,蛋糕和小礼物各买一个,他的预算不超过x元。蛋糕 cake 和小礼物 gift 都有多种价位的可供选择。
输入描述第一行表示cake的单价,以逗号分隔。
第二行表示gift的单价,以逗号分隔。
第三行表示 x 预算。
输出描述输出数字表示购买方案的总数。
补充说明1 ≤ cake.length ≤ 10^{5}
1 ≤ gift.length ≤10^{5}
1 ≤ cake[], gift[] ≤ 10^{5}
1 ≤ X ≤2 * 10^{5}
------------------------------------------------------
示例
示例1
输入10,20,5
5,5,2
15
输出6
说明小牛有6种购买方案,所选蛋糕与所选礼物在数组中对应的下标分别是:
第1种方案: cake[0]+ gift[0] = 10 + 5 = 15;
第2种方案: cake[0]+ gift[1] = 10 + 5 = 15;
第3种方案: cake[0]+ gift[2] = 10 + 2 = 12;
第4种方案: cake[2]+ gift[0] = 5 + 5 = 10;
第5种方案: cake[2]+ gift[1] = 5 + 5 = 10;
第6种方案: cake[2]+ gift[2] = 5 + 2 = 7。


解读与分析

题目解读

给定 2 组数据,在两组数据中各取 1 个,使 2 个数字之和不高于指定值 x。

分析与思路

如果逐个遍历两组数字中每一种组合,时间复杂度为 O(n^{2})。由于 cake、gift 的最大长度为 10^{5},当它们长度较大时,性能会变得很差,我们有更好的方法。

实现如下:
1. 对 cake、gift 进行排序,从大到小。
2. 对 cake 进行二分查找,从 cake 中找到值小于 x 的最大值所对应的下标,设为 minCake。此时,计算出cake 中可能买的 cake 下标范围是 [ minCake, cake.length - 1]。对处于下标范围的 cake 遍历(假设当前正遍历到的下标为 i),进行步骤 3 操作。
3. 如步骤 2,假设当前的 cake 是 cake[i],那么所能购买的 gift 最大价格为 x - cake[i],设为 giftMaxValue。使用二分查找,找到价格不高于 giftMaxValue 的最大值,设下标为 j,那么 gift 的下标可选范围是 [ j, gift.length -1 ]。即意味着当选择 cake[i] 时,gift 的可选个数是 gift.length - j。
4. 继续遍历下一个 cake,即下一个 i,如步骤 3 中,重新计算 giftMaxValue,此时的 giftMaxValue 一定大于前一个计算出来的 giftMaxValue,即意味着这一轮中 gift 下标的 j 的范围一定在 0 和上一轮计算出来的 j 之间,对 [ 0, 上一轮计算的 j ] 进行二分查找,找到不大于 giftMaxValue 的最大值(即最下小标),即计算出选择当前 cake 时,gift 的可选个数。
5. 继续进行步骤 4,直至遍历完所有的 cake,最终所有可选个数之和,即为购买方案总数。

这种方案的时间复杂度为O(nlogn),空间复杂度O(n)。


代码实现

Java代码

import java.util.Arrays;
import java.util.Scanner;
import java.util.Comparator;/*** 生日礼物* * @since 2023.10.31* @version 0.1* @author Frank**/
public class BirthdayGift {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String input = sc.nextLine();String[] strNumber = input.split(",");Integer[] cakes = new Integer[strNumber.length];for (int i = 0; i < strNumber.length; i++) {cakes[i] = Integer.parseInt(strNumber[i]);}input = sc.nextLine();strNumber = input.split(",");Integer[] gifts = new Integer[strNumber.length];for (int i = 0; i < strNumber.length; i++) {gifts[i] = Integer.parseInt(strNumber[i]);}input = sc.nextLine();int x = Integer.parseInt(input);processBirthdayGift(cakes, gifts, x);}}private static void processBirthdayGift(Integer[] cakes, Integer[] gifts, int x) {	// 从大到小排序Comparator<Integer> comp = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}};Arrays.sort( cakes, comp );Arrays.sort( gifts, comp );int cakesFromIndex = findMaxValueIndex( x - 1, cakes.length - 1, cakes );int sum = 0;int highIndex = gifts.length - 1;for( int i = cakesFromIndex; i < cakes.length; i ++ ){int giftMaxValue = x - cakes[i];highIndex = findMaxValueIndex( giftMaxValue, highIndex, gifts );sum += ( gifts.length - highIndex ) ;}	System.out.println( sum );}private static int findMaxValueIndex( int maxValue, int highIndex, Integer[] srcArr ){// 已排序从大到小的数组,取值范围在 [0, fromIndex]int low = 0;int high = highIndex;int mid = ( low + high ) / 2;while( low <= high ){mid = ( low + high ) / 2;if( maxValue == srcArr[mid] ){// 相等,还需判断所有相等的情况while( mid >= 1 && srcArr[mid - 1 ] == srcArr[mid]){mid --;}return mid;}else if( maxValue > srcArr[mid] ){high = mid - 1;}else{low = mid + 1;}}// 此时 low > highif( high < 0 ){return 0;}if( srcArr[ high ] < maxValue ){return high;}if( srcArr[low] < maxValue ){return low;}if( low + 1 <= srcArr.length -1 ){return low + 1;}else{return srcArr.length -1;}}
}

JavaScript代码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {while (line = await readline()) {var strNumber = line.split(",");var cakes = new Array();for (var i = 0; i < strNumber.length; i++) {cakes[i] = parseInt(strNumber[i]);}line = await readline();var strNumber = line.split(",");var gifts = new Array();for (var i = 0; i < strNumber.length; i++) {gifts[i] = parseInt(strNumber[i]);}line = await readline();var x = parseInt(line);processBirthdayGift(cakes, gifts, x);}
}();function processBirthdayGift(cakes, gifts, x) {// 从大到小排序var comp = function( a, b) {return b - a;        };cakes.sort( comp );gifts.sort( comp );var cakesFromIndex = findMaxValueIndex( x - 1, cakes.length - 1, cakes );var sum = 0;var highIndex = gifts.length - 1;for( var i = cakesFromIndex; i < cakes.length; i ++ ){var giftMaxValue = x - cakes[i];highIndex = findMaxValueIndex( giftMaxValue, highIndex, gifts );sum += ( gifts.length - highIndex ) ;}   console.log( sum );
}function findMaxValueIndex(maxValue, highIndex, srcArr) {// 已排序从大到小的数组,取值范围在 [0, fromIndex]var low = 0;var high = highIndex;var mid = parseInt( (low + high) / 2 );while (low <= high) {mid = parseInt( (low + high) / 2 );if (maxValue == srcArr[mid]) {// 相等,还需判断所有相等的情况while (mid >= 1 && srcArr[mid - 1] == srcArr[mid]) {mid--;}return mid;} else if (maxValue > srcArr[mid]) {high = mid - 1;} else {low = mid + 1;}}// 此时 low > highif (high < 0) {return 0;}if (srcArr[high] < maxValue) {return high;}if (srcArr[low] < maxValue) {return low;}// should never come hereif (low + 1 <= srcArr.length - 1) {return low + 1;} else {return srcArr.length - 1;}
}

(完)

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

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

相关文章

通过python操作neo4j

在neo4j中创建结点和关系 创建结点 创建电影结点 例如&#xff1a;创建一个Movie结点&#xff0c;这个结点上带有三个属性{title:‘The Matrix’, released:1999, tagline:‘Welcome to the Real World’} CREATE (TheMatrix:Movie {title:The Matrix, released:1999, tagl…

Python Django 之模板继承详解(extends)

文章目录 1 概述1.1 目的1.2 标签&#xff1a;block、extends1.3 目录结构 2 templates 目录2.1 base.html&#xff1a;父页面2.2 login.html&#xff1a;子页面 3 其它代码3.1 settings.py3.2 views.py3.3 urls.py 1 概述 1.1 目的 模板继承 和 类继承 的目的是一样的&#…

【P2P owt】owt-client-native-p2p-e2e-test vs2017构建7:依赖库及路径

依赖库 G:\CDN\LiveServiceMesh\cdnsignal\third_party\libeva\thirdparty\janbar-openssl\out32\ssl\Debug\libssl-

2、NLP文本预处理技术:词干提取和词形还原

一、说明 在上一篇文章中&#xff0c;我们解释了文本预处理的重要性&#xff0c;并解释了一些文本预处理技术。在本文中&#xff0c;我们将介绍词干提取和词形还原主题。 词干提取和词形还原是两种文本预处理技术&#xff0c;用于将单词还原为其基本形式或词根形式。这些技术的…

SpringBoot集成与应用Neo4j

文章目录 前言集成使用定义实体配置定义Repository查询方法方式一&#xff1a;Query方式二&#xff1a;Cypher语法构建器方式三&#xff1a;Example条件构建器方式四&#xff1a;DSL语法 自定义方法自定义接口继承自定义接口实现自定义接口neo4jTemplateNeo4jClient 自定义抽象…

企业级JAVA、数据库等编程规范之命名风格 —— 超详细准确无误

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信你对这两篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc; 表白墙/留言墙 —— 初级SpringBoot项目&#xff0c;练手项目前后端开发(带完整源码) 全方位全步骤手把手教学 &#x1f4dc; 用户登录前后端…

【计算机网络笔记】传输层——可靠数据传输原理之Rdt协议

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

基于深度学习的人脸表情识别 计算机竞赛

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸表情识别 该项目较…

视频汇聚平台EasyCVR分发的流如何进行token鉴权?具体步骤是什么?

视频监控EasyCVR平台能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#xff0c;也能支持视…

智安网络|保护您的应用程序免受攻击:重要的安全强化措施

在今天的数字化时代&#xff0c;应用程序安全成为了企业和个人必须重视的重要领域。应用程序普遍存在的安全漏洞成为黑客们进行攻击的一个突破口。为了保护敏感数据和个人隐私&#xff0c;我们必须了解并实施一系列的关键措施来加固应用程序的安全性。 首先&#xff0c;一个关…

SSM培训报名管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 培训报名管理系统是一套完善的信息系统&#xff0c;结合SSM框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主 要采用B/S模式开…

Mac docker+vscode

mac 使用docker vs code 通过vscode 可以使用docker容器的环境。 可以在容器安装gdb, 直接调试代码。 创建容易时候可以指定目录和容易目录可以共享文件。

十年回望 -- JAVA

十年 十年时间&#xff0c;弹指一挥&#xff0c;好像一直都是在为工作奔波&#xff0c;匆匆忙忙的十年。 一、个人介绍 本人毕业于一所很普通的公办专科院校&#xff08;全日制统招大专&#xff09;&#xff0c;专业是软件技术&#xff0c;当初能进入计算机这一行业&#xff0…

数字孪生与智慧城市:开启未来智慧生活

在数字时代的浪潮中&#xff0c;数字孪生技术和智慧城市的理念相互交织&#xff0c;共同塑造了一个更智能、更可持续、更宜居的未来。数字孪生是一项前沿技术&#xff0c;将虚拟世界与现实世界相融合&#xff0c;为城市管理者和市民带来了前所未有的机遇和便捷。 数字孪生模型是…

FreeRTOS深入教程(空闲任务和Tick中断深入分析)

文章目录 前言一、空闲任务源码分析二、Tick中断深入分析总结 前言 本篇文章主要带大家深入分析空闲任务和Tick中断的作用。 一、空闲任务源码分析 在启动调度器时会创建出空闲任务&#xff1a; /* 启动调度器 */ vTaskStartScheduler();在空闲任务中会调用到prvCheckTasks…

Unity地面交互效果——2、动态法线贴图实现轨迹效果

Unity引擎动态法线贴图制作球滚动轨迹 大家好&#xff0c;我是阿赵。   之前说了一个使用局部UV采样来实现轨迹的方法。这一篇在之前的基础上&#xff0c;使用法线贴图进行凹凸轨迹的绘制。 一、实现的目标 先来回顾一下&#xff0c;上一篇最终我们已经绘制了一个轨迹的贴图…

ASCB1系列智能微型断路器在科技馆中的应用-安科瑞黄安南

【摘要】&#xff1a;安科瑞电气厂家直供黄安南1876-15//06-237&#xff0c;ASCB1系列智能微型断路器是安科瑞电气股份有限公司全新推出的智慧用电产品&#xff0c;产品由智能微型断路器与智能网关两部分组成&#xff0c;可用于对用电线路的关键电气因素&#xff0c;如电压、电…

数据交易是什么?国内的数据交易有哪些?

目录 数据交易是什么&#xff1f;国内的数据交易有哪些&#xff1f; 数据交易的概念 国内数据交易发展历程 数据交易主体 国内数据交易市场面临的问题 如何解决&#xff1a; 明确交易标准&#xff0c;推动交易市场&#xff0c;制定规则&#xff0c;完善数据监管机制&…

coturn服务器的搭建

Window下搭建coturn服务器&#xff1a; 准备材料&#xff1a; 1、安装Cygwin&#xff0c;地址&#xff1a;https://cygwin.com/install.html 由于Window无法直接部署coturn&#xff0c;因此需要下载安装Cygwin在Window上部署Linux虚拟环境。 在安装的时候需要安装几下packe…