腾讯2017 暑假实习生编程题---【3】 有趣的数字

Q:小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?


A:之前尝试过暴力解决,结果有内存限制不让过。。。

import java.util.*;

public class T3 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while(input.hasNext()) {
            int num = input.nextInt();    //确定个数
            int[] array = new int[num];    //初始化数组
            for (int n = 0; n < num; n++) {
                array[n] = input.nextInt();
            }
            Arrays.sort(array);

            find(array, num);
        }
    }

    public static void find(int[] array, int num) {
        int maxNum = 0, minNum = 0, max = array[num - 1] - array[0];
        
        //特殊情况
        if (max == 0) {    //代表所有数都一样.这是特殊情况。
            minNum = maxNum = num * (num - 1) / 2;
            System.out.println(minNum + " " + maxNum);
            return ;
        }

        //寻找最小值!用MAP解决问题!
        //先用map统计各个数的个数。
        //SITN1 : 如果没有重复数字,则value均为1,遍历数组,寻找最小值以及minNum,没办法。
        //SITN2 : 若有重复数字,则存在value > 1,此时最小delta为0,分别用C(2,value)计算,最后加起来得到minNum。
        //max和maxNum则直接用数组头尾得到array_max & array_min,然后从map中找到对应value,相乘得到数对的数量。
        Map<Integer, Integer> map = new HashMap<>();
        for(int key : array) {
            if (!map.containsKey(key)) {
                map.put(key, 1);
            }
            else {
                int value = map.get(key);
                value++;
                map.put(key, value);
            }
        }

        //find maxNum
        int temp1 = map.get(array[0]), temp2 = map.get(array[num - 1]);
        maxNum = temp2 * temp1;

        //find minNum
        /*怎么判断有没有重复数字?遍历value。
        1.如果每个value都是1,就没有重复,此时调用——————noRepetitiveFinder
        2.一旦出现value != 1 ,则必定有重复的,此时调用——————repetitiveFinder */
        Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
        boolean check = false;    //用于检查是否已经有了minNum.
        for (Map.Entry<Integer, Integer> entry : entrySet) {
            if (entry.getValue() != 1) {
                minNum = repetitiveFinder(map);
                check = true;
                break;
            }
        }

        if (check == false)
            minNum = noRepetitiveFinder(array);


        System.out.println(minNum + " " + maxNum);
    }

    private static int noRepetitiveFinder(int[] array) {
        int min = Integer.MAX_VALUE, minNum = 0; 
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                int delta = array[j] - array[i];
                if (delta < min) {
                    minNum = 1;
                    min = delta;
                }
                else if (delta == min) {
                    minNum++;
                }
                else {
                    ;
                }
            }
        }

        return minNum;
    }

    //有重复说明最小值为0.
    private static int repetitiveFinder(Map map) {
        int minNum = 0;    
        Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
        for (Map.Entry<Integer, Integer> entry : entrySet) {
            if (entry.getValue() != 1) {
                int value = entry.getValue();
                minNum += value * (value - 1) / 2;   
            }
        }

        return minNum;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值