全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:服务中心的最佳位置
知识点:二分查找、双指针
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
一家快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置,并希望能够以此为依据为新的服务中心选址:使服务中心 到所有区域的距离的总和最小。
给你一个数组 positions ,其中 positions[i] = [left, right] 表示第 i 个区域在街道上的位置,其中 left 代表区域的左侧的起点, right 表示区域的右侧终点,设择服务中心的位置为 location。
如果第 i 个区域的右侧起点 right 满足 right < location ,则第 i 个区域到服务中心的距离为 location – right;
如果第 i 个区域的左侧起点 left 满足 left > location ,则第 i 个区域到服务中心的距离为 left – location;
如果第 i 个区域的两侧 left, right 满足 left <= location <= right ,则第 i 个区域到服务中心的距离为 0;
选择最佳的服务中心的位置为 location ,请返回最佳的服务中心位置到所有区域的距离总和的最小值。
输入描述:
先输入区域数组positions的长度n(1 <= n <= 10^5)
接下来n行每行输入成对的left和right值,以空格隔开
-10^9 <left <= 10^9
-10^9 <right<= 10^9
输出描述:
输出为location
补充说明:
不同的 positions 的区间可能存在重叠;
location 的位置可以有多个
示例1
输入:
3
1 2
3 4
10 20
输出:
8
说明:
我们选择最佳服务中心位置为3,此时3到 区域[1,2]的距离为1, 3到区域[3,4]的距离为0,3到区域[10,20]的距离为7。最小的距离为8。
示例2
输入:
2
1 4
4 5
输出:
0
说明:
我们选择最佳服务中心位置可以选择4,此时的最小距离为0
示例3
输入:
4
1 3
2 6
8 10
15 18
输出:
14
说明:
我们选择最佳服务中心位置可以选择7,此时的最小距离为14
解题思路:
算法一:
暴力计算所有位置到各街道距离和,求出其中最小值;
算法二:使用二分法
计算最左侧到各街道的距离和left,最右侧到各街道的距离和right,中间位置到各街道的距离和mid;
如果left<right,则right=mid;否则left=mid;以此类推。。。
这道题的正确率也是感人,我看到的最高分是54分。以下是找到的真机用例:
4 4 5 6 1 8 7 15 2 4 正确答案:3
2 2 1 4 4 5 正确答案:0
5 6 1 3 4 9 2 15 6 27 15 17 5 8 正确答案:12
10 16 41 67 0 34 24 69 58 78 62 64 5 45 27 81 61 91 42 95 27 36 4 91 2 53 82 92 16 21 18 95 26 47 正确答案:127
算法一代码实现:
package com.codernav.demo.hwod.exam; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * @title 服务中心的最佳位置 * @Description 一家快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置,并希望能够以此为依据为新的服务中心选址:使服务中心 到所有区域的距离的总和最小。 * 给你一个数组 positions ,其中 positions[i] = [left, right] 表示第 i 个区域在街道上的位置,其中 left 代表区域的左侧的起点, right 表示区域的右侧终点,设择服务中心的位置为 location。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/28 */ public class Main { public static List<int[]> list = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int i = 0; i < n; i++) { int[] ints = new int[2]; ints[0] = sc.nextInt(); ints[1] = sc.nextInt(); list.add(ints); } /** * 对线段进行排序 * 左边界小的在前 * 左边界相等的右边界小的在前 */ list.sort((a, b) -> { if (a[0] == b[0]) { return a[1] - b[1]; } return a[0] - b[0]; }); //最左边的坐标 int min = list.get(0)[0]; //最右边的坐标 int max = list.get(n - 1)[1]; //距离最小值 int res = Integer.MAX_VALUE; for (int i = min; i <= max; i++) { res = Math.min(res, handle(i)); } System.out.println(res); } /** * 求出服务中心到所有街道的距离和 * * @param mid * @return */ public static int handle(int mid) { int res = 0; for (int[] ints : list) { int a = ints[0]; int b = ints[1]; if (mid < a) { res += a - mid; } else if (mid > b) { res += mid - b; } } return res; } }
算法二代码实现:
package com.codernav.demo.hwod.exam; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * @title 服务中心的最佳位置 * @Description 一家快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置,并希望能够以此为依据为新的服务中心选址:使服务中心 到所有区域的距离的总和最小。 * 给你一个数组 positions ,其中 positions[i] = [left, right] 表示第 i 个区域在街道上的位置,其中 left 代表区域的左侧的起点, right 表示区域的右侧终点,设择服务中心的位置为 location。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/28 */ public class Main { public static List<int[]> list = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int i = 0; i < n; i++) { int[] ints = new int[2]; ints[0] = sc.nextInt(); ints[1] = sc.nextInt(); list.add(ints); } /** * 对线段进行排序 * 左边界小的在前 * 左边界相等的右边界小的在前 */ list.sort((a, b) -> { if (a[0] == b[0]) { return a[1] - b[1]; } return a[0] - b[0]; }); int left = list.get(0)[0]; int right = list.get(n - 1)[1]; //最左侧到各街道的距离和 int leftDance = handle(left); //最右侧到各街道的距离和 int rightDance = handle(right); while (right - left > 1) { //中心位置 int mid = (right + left) / 2; //中心位置到各街道的距离总和 int midDance = handle(mid); //距离和较小的位置 int min = Math.min(leftDance, rightDance); if (leftDance == min) { //左侧位置较小则右侧变成中心位置 right = mid; rightDance = midDance; } else { //右侧位置较小则左侧变成中心位置 left = mid; leftDance = midDance; } } System.out.println(Math.min(leftDance, rightDance)); } /** * 求出所有距离和 * * @param mid * @return */ public static int handle(int mid) { int res = 0; for (int[] ints : list) { int a = ints[0]; int b = ints[1]; if (mid < a) { res += a - mid; } else if (mid > b) { res += mid - b; } } return res; } }