【华为OD题库-046】生日礼物-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的数:

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

找到第一个大于x的数:

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

找最后一个:

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

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

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

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

题解

暴力查找

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;
    }
}

二分法

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),查看当前专栏更新的所有题目。

说明

本专栏所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_31076523/article/details/134176793。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

  • 28
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为od机试中,新学校选址问题是一个关于使用Java语言解决的问题。在解决这个问题时,我们可以通过以下步骤来完成。 首先,我们需要理解问题的要求和限制条件。新学校选址的目标是在一个给定的地图上找到一个合适的位置来建设新学校。这个位置应满足一定的条件,比如与周围的住宅区距离不宜过远,应尽可能靠近居民区。限制条件可能还包括学校面积和周边环境等。 接下来,我们需要获取地图的数据。可以通过读取一个地图文件或者从数据库中查询地图数据来获得地图的信息。地图数据的存储方式可以灵活选择,比如使用二维数组或者邻接矩阵。 然后,我们需要编写一个Java程序来实现新学校选址算法。可以使用图的遍历算法,比如深度优先搜索(DFS)或广度优先搜索(BFS)来实现。算法的核心是通过递归或循环遍历地图上的每一个位置,并根据选址条件进行判断和筛选。 最后,我们需要输出选址结果。可以将选定的位置以某种方式标记在地图上,比如输出一个新的地图文件或者在图形界面中显示。同时,还可以输出选址的具体坐标和其他相关信息,以便后续的学校建设工作。 总之,通过使用Java语言,我们可以通过一个新学校选址问题来展示我们在算法设计和编程方面的能力。相信在华为od机试中,通过合理的数据处理和算法实现,我们可以解决这个问题并得出满意的选址结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值