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;
}
}