首页 > 试题广场 >

IP段合并

[编程题]IP段合并
  • 热度指数:1475 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
一个数字段由首尾两个数字标识,表示一个自然数集合,
比如数字段[beg, end)表示从beg到end之间的所有自然数,
包含beg,但不包含end。

有若干个数字段,这些数字段之间可能有重叠,
怎么把这些数字段合并去重,用最少个数的数字段来表示。

合并前后,整个集合包含的数字不发生变化。



输入描述:
第一行为数字N,表示接下来有N个数字段(N<=100000)
第二行开始一共有N行,每行两个数字,分别表示一个数字段的beg和end
(beg和end为无符号32位整数)


输出描述:
合并去重后形成的数字段集合,按升序排列。
示例1

输入

4 
3 8
3 7
4 6
7 9

输出

3 9
先把数据按照左值小的,右值大的排序,然后再遍历整个数组。如果两个值对(a,b),(c,d),如果a<=b
&&b>=d那么对于(a,b)来说,(c,d)就可以被合并,如果b<d那么就可以把b的值替换为d,把(a,b)更新为
(a,d),如果c>b那么就意味着一个区间不能表示(a,b)和(c,d),必须要用两个区间来表示。遍历
一遍数组就行了。

import java.util.*;

public class Main{
    static class Pair implements Comparable<Pair>{
        public int a;
        public int b;
        public Pair(int a,int b){
            this.a=a;
            this.b=b;
        }
        @Override
        public int compareTo(Pair p){
            if(a==p.a) return p.b-b;
            else return a-p.a;
        }
    }
    public static void main(String[] args){
           Scanner sc=new Scanner(System.in);
           int n=sc.nextInt();
           Pair[] ps=new Pair[n];
           for(int i=0;i<n;i++){
               int k=sc.nextInt();
               int l=sc.nextInt();
               ps[i]=new Pair(k,l);
           }
           Arrays.sort(ps);
           /*for(int i=0;i<n;i++){
               System.out.println(ps[i].a+" "+ps[i].b);
           }*/
            List<Pair> result=new ArrayList<>();
            Pair now=ps[0];
            for(int i=1;i<n;i++){
                if(now.a<=ps[i].a&&now.b>=ps[i].b){
                    continue;
                }else if(ps[i].a>now.b){
                    result.add(now);
                    now=ps[i];
                }
                 else now.b=ps[i].b;
            }
            result.add(now);
            for(Pair p:result){
           System.out.println(p.a+" "+p.b);
          }
           sc.close();
    }
    
}

发表于 2019-08-04 18:29:03 回复(0)