华为OD题目:区间连接器

华为OD题目:区间连接器

知识点数组排序Q滑窗
时间限制: 1s 空间限制: 256MB 限定语言: 不限
题目描述
有一组区间[a0,b0],[a1,b1],…(a,b 表示起点,终点),区间有可能重叠、相邻,重鲁或相邻则可以合并为更大的区间:
给定一组连接器[x1,x2,x3,.] (x 表示连接器的最大可连接长度,即 x>=gap),可用于将分离的区间连接起来,但两个分离区间之间只能使用1个连接器;
请编程实现使用连接器后,最少的区间数结果。

区间数量 <10000: a,b 均 <=10000
连接器梳理 <10000:x <=10000

输入描述:
区间组: [1,10],[15,20],[18,30],[33,40]
连接器组: [5,4,3,2]
输出描述:
说明: 合并后: [1,10],[15,30],[33,40],使用 5,3 两个连接器连接后只剩下[1,40]

示例1
输入:
[1,10],[15,20],[18,30],[33,40]
[5,4,3,2]
输出:
1

说明:
合并后: [1,10],[15,30],[33,40],使用 5,3 两个连接器连接后只剩下[1,40]
示例2
输入:
[1,2],[3,5],[7,10],[15,20],[30,100]
[5,4,3,2,1]
输出:
2
说明:
无重叠和相邻,使用 1,2, 5 三个连接器连接后只剩下[1,20],[30,100]

解题思路:
1、对区间进行升序排序:
2将相邻和存在交集的区间进行合并
3求得步骤2中各区间的距离集合
4将步骤3的集合与连接器集合进行比较 (使用双指针进行比较)
注:使用过的连接器不能继续使用:连接器取最接近的

public class My {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] regionsStr = line.replaceAll("\\[","")
                .replaceAll("]","")
                .split(",");
        //区间集合
        List<int[]> list = new ArrayList<>();
        //组装数据
        for( int i=0; i<regionsStr.length; i+=2){
            int left = Integer.parseInt(regionsStr[i]);
            int right = Integer.parseInt(regionsStr[i+1]);
            list.add(new int[]{ left, right});
        }

        String linkStr = sc.nextLine();
        //连接器数组
        int[] linkArr = getArr(linkStr);

        //对list按照左侧进行升序排列
        list.sort((a1, a2) -> a1[0] - a2[0]);
        //对连接器进行升序排列
        Arrays.sort(linkArr);

        //先将区间进行合并
        List<int[]> mergedList = new ArrayList<>();
        int[] pre = list.get(0);
        mergedList.add(pre);
        for (int i = 1; i < list.size(); i++) {
            int[] currRegion = list.get(i);
            //如果当前区域左端点 <- 已经合并的右端点,那么可以把当前节点并入进去
            if (currRegion[0] <= pre[1]) {
                pre[1] = currRegion[1];
            }else {
                //否则,合并不了
                mergedList.add(currRegion);
                pre = currRegion;
            }
        }

        //初始化第一个连接区域
        int[] preRegion = mergedList.get(0);
        int[] gapArr = new int[mergedList.size() - 1];
        for (int i = 1, j = 0; i < mergedList.size(); i++, j++) {
            int[] region = mergedList.get(i);
            //左端点减去前面区域的右端点
            int gap = region[0] - preRegion[1];
            gapArr[i - 1] = gap;
            preRegion = region;
        }

        Arrays.sort(gapArr);
        //获取使用了连接器的个数
        int usedLinkNum = getUsedLink(gapArr, linkArr);
        //usedLinkNum个连接器可以连接 usedLinkNum+1个区域
        int remain = mergedList.size() - usedLinkNum;
        System.out.println(remain);


    }

    public static int[] getArr(String str) {
        String replace1 = str.replace("[", "");
        String replace2 = replace1.replace("]", "");

        String[] split = replace2.split(",");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        return arr;
    }

    //获取使用了的连接器的数量
    public static int getUsedLink(int[] gapArr, int[] linkArr) {
        //用i, j两个指针分别指gap数组和连接器数组的下标
        int i = 0;
        int j = 0;
        int usedNum = 0;
        while (i < gapArr.length && j < linkArr.length) {
            if (linkArr[j] >= gapArr[i]) {
                System.out.println(" used link=" + linkArr[j]);
                i++;
                j++;
                usedNum++;
            }else {
                j++;
            }
        }
        return usedNum;

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值