有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?

   有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?

输入描述:

输入包含多组测试数据。 对于每组测试数据: N - 本组测试数据有n个数 a1,a2...an - 需要计算的数据 保证: 1<=N<=100000,0<=ai<=INT_MAX.



输出描述:

对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。


输入例子:
6
45 12 45 32 5 6
输出例子:
1 2
先用快排,然后对有序数组分别求差值最大的对数和差值最小的对数。
快排之后,如果数组为常数数组,即最大值=最小值,则结果已经出来了。否则,进行下面的操作,其中:
1. 差值最大的好求,看有序数组有几个最小值和几个最大值,相乘即可。
2. 差值最小的,由于是有序数组,必定是相邻的差值较小,故由快排后的有序数组生成差值数组(即相邻的两两相减)。如果差值数组中0,则查看差值数组中连续0的组数,可以由排列组合知识计算总的差值最小的对数;如果差值数组中没有0,则只需计算差值数组中有多少个最小值即可。注:差值数组必定都是非负数。
3. 空间复杂度较大,需要一些辅助数组。
4. 时间复杂度:快排O(NlogN),求差值最大O(N),求差值最小O(N),所以最终的时间复杂度为O(NlogN)。

importjava.util.Arrays;
importjava.util.Scanner;
 
publicclass Jd_NumAbs {
    privatestatic Scanner scanner = newScanner(System.in);
 
    publicstatic void main(String[] args) {
        while(scanner.hasNext()) {
            intnum = scanner.nextInt();
            int[] nums = newint[num];
            for(inti = 0; i < num; i++) {
                nums[i] = scanner.nextInt();
            }
            // getMinMaxAbsNums(nums, num);
            fun2(nums, num);
        }
    }
 
    publicstatic void getMinMaxAbsNums(int[] nums, intlen) {
        intminNum = 0, maxNum = 0;
        intmin = Integer.MAX_VALUE;
        intmax = Integer.MIN_VALUE;
        for(inti = 0; i < len - 1; i++) {// 时间复杂度n^2
            for(intj = i + 1; j < len - 1; j++) {
                intabs = Math.abs(nums[i] - nums[j]);
                if(abs < min) {
                    minNum = 1;
                    min = abs;
                } elseif (min == abs) {
                    minNum++;
                } elseif (abs > max) {
                    max = abs;
                    maxNum = 1;
                } elseif (max == abs) {
                    maxNum++;
                }
            }
        }
        System.out.println(minNum + " " + maxNum);
    }
 
    publicstatic void fun2(int[] nums, intlen) {
        Arrays.sort(nums);// 时间复杂度nlogn
        intmaxCount = 0;
        intminNum = 1, maxNum = 1;// 数组中最小和最大元素的个数
        inti = 1;
        while(i < len && nums[i - 1] == nums[i]) {
            minNum++;
            i++;
        }
        i = len - 2;
        while(i >= 0&& nums[i] == nums[i + 1]) {
            maxNum++;
            i--;
        }
        if(nums[0] == nums[len - 1]) {
            maxCount = len * (len - 1) / 2;
        } else{
            maxCount = minNum * maxNum;
        }
        for(intj = 1; j < len; j++) {
            nums[j - 1] = Math.abs(nums[j] - nums[j - 1]);
        }
        intminValue = Integer.MAX_VALUE;
        intminCount = 0;
        for(intj = 0; j < nums.length; j++) {//初次统计minValue
            if(nums[j] < minValue) {
                minCount = 1;
                minValue=nums[j];
            } elseif (nums[j] == minValue) {
                minCount++;
            }
        }
        if(minValue==0){//如果最小差值为0,统计0的区间个数
            minCount=0;
            inttempMinCount=0;
            for(intj = 0; j < len-1; j++) {
                if(nums[j]==0) {
                    tempMinCount++;
                }else{
                    minCount+=tempMinCount*(tempMinCount+1)/2;
                    tempMinCount=0;
                }
            }
            minCount+=tempMinCount*(tempMinCount+1)/2;
        }
        System.out.println(minCount + " " + maxCount);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值