【华为OD题库-046】生日礼物-java

news/2024/7/20 17:34:47 标签: 华为od, java, 二分查找

题目

小牛的孩子生日快要到了,他打算给孩子买蛋糕和小礼物,蛋糕和小礼物各买一个,他的预算不超过x元。蛋糕cake和小礼物gift都有多种价位的可供选择。
请返回小牛共有多少种购买方案
输入描述
第一行表示cake的单价,以逗号分隔
第二行表示gift的单价,以逗号分隔
第三行表示x预算
输出描述
输出数字表示购买方案的总数
备注
1< cake.length ≤ 10^5
1 < gift.length <10^5。
1<cake[i], gift[i]<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.

思路

简单题,有以下思路

1. 暴力解法

将cases和gift按照从小到大排序,两层for循环即可求解:
当cakes[i] + gift[j] <= n,说明未超预算,结果+1
否则,超过了预算,因为已经从小到大排序,后续遍历只会使预算更大,所以应该break内层循环
继续外层循环
最后返回结果即可

2. 二分查找

因为题目要求买两种礼物,那么第一种礼物的价格应该小于x,即范围应该为:[1,x)
第二种的礼物价格为:x-第一种礼物的价值,此时右边应该取等,即范围为:[1,x-price1]
可以看到本题转化为了以下两个二分查找问题:

  1. 对于给定排序数组,找到最后一个小于target的位置
  2. 对于给定排序数组,找到最后一个不大于target的位置

因为两种要求二分法写法基本相同,所以可以融合到一个函数里去,详见题解

补充

二分法各种模板:

找第一个:

找到第一个大于等于x的数:

java">			mid=l+r>>1
            if (nums[mid] >= x) {
                r = mid;
            }  else {
 				l = mid+1;
            }

找到第一个大于x的数:

java">			mid=l+r>>1
			if (nums[mid] > x) {
                r = mid;
            }  else {
 				l = mid+1;
            }

找最后一个:

找到最后一个小于x的数:

java">			mid=l+r+1>>1
			if (nums[mid] < x) {
               l = mid;
            }  else {
 				r=mid-1;
            }

找到最后一个小于等于x的数:

java">			mid=l+r+1>>1
			if (nums[mid] <= x) {
               l = mid;
            }  else {
 				r=mid-1;
            }

题解

暴力查找

java">package hwod;

import java.util.Arrays;
import java.util.Scanner;

public class BirthDayGift {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] cakes = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        int[] gift = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        int n = sc.nextInt();
        System.out.println(birthDayGift(cakes, gift, n));

    }


    private static int birthDayGift(int[] cakes, int[] gift, int n) {
        Arrays.sort(cakes);
        Arrays.sort(gift);
        int res = 0;
        for (int i = 0; i < cakes.length; i++) {
            for (int j = 0; j < gift.length; j++) {
                if (cakes[i] + gift[j] <= n) res++;
                else break;
            }
        }
        return res;
    }
}

二分法

java">package hwod;

import java.util.Arrays;
import java.util.Scanner;

public class BirthDayGift {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] cakes = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        int[] gift = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        int n = sc.nextInt();
        System.out.println(birthDayGift(cakes, gift, n));

    }
    private static int birthDayGift(int[] cakes, int[] gift, int n) {
        Arrays.sort(cakes);
        Arrays.sort(gift);
        int res = 0;
        int idx = findGreatThanTarget(cakes, n, false);
        for (int i = 0; i <= idx; i++) {
            res += findGreatThanTarget(gift, n - cakes[i], true) + 1;
        }

        return res;
    }

    //flag取false:nums为从小到大排序的数组,找到最后一个小于target的位置
    //flag取true:nums为从小到大排序的数组,找到最后一个不大于target的位置
    private static int findGreatThanTarget(int[] nums, int target, boolean flag) {
        int l = 0, r = nums.length - 1;
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (nums[mid] > target) {
                r = mid - 1;
            } else if (nums[mid] < target) {
                l = mid;
            } else {
                if (flag) l = mid;
                else r = mid - 1;
            }
        }
        return l;
    }
}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。


http://www.niftyadmin.cn/n/5224685.html

相关文章

redis的数据类型的操作增删改查

redis的数据类型的操作增删改查 redis的高可用&#xff1a; 在集群当中有一个非常重要的指标&#xff0c;提供正常服务的时间的百分比&#xff08;365天&#xff09;99.9% redis的高可用的含义要更加宽泛&#xff0c;正常服务是指标之一数据容量扩展&#xff0c;数据的安全性…

CSDN如何完整转载别人的文章并做自己的笔记

1、这篇文章介绍主体的转载&#xff08;粘贴&#xff09;方法&#xff1a; 转载&#xff1a;CSDN快速转载文章方法&#xff08;简单&#xff09;_csdn转载_biggolden1的博客-CSDN博客 2、这篇文章解决&#xff0c;对于含有代码块的文章粘贴后&#xff0c;出现的额外行号块问题…

three.js球体实现

作者&#xff1a;baekpcyyy&#x1f41f; 使用three.js渲染出可以调节大小的立方体 1.搭建开发环境 1.首先新建文件夹用vsc打开项目终端 2.执行npm init -y 创建配置文件夹 3.执行npm i three0.152 安装three.js依赖 4.执行npm I vite -D 安装 Vite 作为开发依赖 5.根…

西工大网络空间安全学院计算机系统基础实验一(45678)

接着来看第4个函数&#xff0c;int replaceByte(int x, int n, int c)&#xff0c;看题目给出的例子&#xff0c;replaceByte(0x12345678,1,0xab) 0x1234ab78。我们可以多写几个例子&#xff0c;进而找出规律&#xff0c;比如&#xff1a; replaceByte(0x12345678,2,0xab) 0…

虚拟机安装centos7系统后网络配置

一.桥接网络和nat网络的区别1&#xff0c;桥接模式&#xff08;如果外部访问虚拟机&#xff0c;最好选这个&#xff09; 通过使用物理机网卡 具有单独ip,但是需要手动配置。 在bridged模式下&#xff0c;VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机&#xff0c;它…

不测试,不安全 —— 安全测试的重要性!

1、 什么是安全测试 安全测试是一种软件测试&#xff0c;可发现软件应用程序中的漏洞&#xff0c;威胁&#xff0c;风险并防止来自入侵者的恶意攻击。 安全测试的目的是确定软件系统的所有可能漏洞和弱点&#xff0c;这些漏洞和弱点可能导致信息&#xff0c;收入损失&#xff…

android 内存分析(待续)

/proc/meminfo memory状态解读 命令&#xff1a;adb shell cat /proc/meminfo内存分布log 查看方式 命令&#xff1a;adb shell cat /proc/meminfo 用途:可以整体的了解memory使用情况 我们说的可用memory一般以MemAvailable的数据为准。所以了解MemAvailable的组成可以帮助…

使用Golang构建高性能网络爬虫

前段时间和以前公司的老同事聚会&#xff0c;喝酒中无意聊到目前他们公司在做的一个爬虫项目&#xff0c;因为效率低下&#xff0c;整个人每天忙的不可开交。借着这次聚会&#xff0c;正好询问我一些解决方案。于是&#xff0c;我给了他们我的一些思路。 所谓的高性能网络爬虫…