有趣的数字
来源:牛客网
http://www.nowcoder.com/questionTerminal/af709ab9ca57430886632022e543d4c6
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差的绝对值最小的有多少对呢?差的绝对值最大的呢?
输入描述:
输入包含多组测试数据。
对于每组测试数据:
N - 本组测试数据有n个数
a1,a2...an - 需要计算的数据
保证:
1<=N<=100000,0<=ai<=INT_MAX.
输出描述:
对于每组数据,输出两个数,第一个数表示差的绝对值最小的对数,第二个数表示差的绝对值最大的对数。
输入例子:
6
45 12 45 32 5 6
输出例子:
1 2
注意到题目中N的范围为10W,有点大。我试了下,直接两层for循环尝试所有的两两组合,会超时,O(n^2)的时间复杂度。
那么用n*logn 复杂度的算法试试呢。调用java Arrays.sort() 方法将数组排序,差绝对值最大的就是首尾两个数;最小的是依次比较相邻两个数的绝对值差。
注意的地方是(1)有相同的数,那么差绝对值最小的是0;所有数一样的情况。具体见代码:比较杂乱,折叠了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 4 public class TT { 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 while (sc.hasNext()) { 8 int N = sc.nextInt(); 9 int[] a = new int[N]; 10 for (int i = 0; i < N; ++i) 11 a[i] = sc.nextInt(); 12 13 Arrays.sort(a);// time complexity n*logn 14 15 int smallest = Integer.MAX_VALUE, smlTimes = 0; 16 int largest = Integer.MIN_VALUE, lagTimes = 0; 17 18 int start = 1; 19 for (int i = 1; i < N; ++i) { 20 if (a[i] == a[i - 1]) { 21 start = i; 22 smlTimes = 0; 23 break; 24 } 25 if (a[i] - a[i - 1] == smallest) smlTimes++; 26 else if (a[i] - a[i - 1] < smallest) { 27 smallest = a[i] - a[i - 1]; 28 smlTimes = 1; 29 } 30 } 31 32 for (int i = start; i < N; ++i) { 33 if (a[i] == a[i - 1]) { 34 int repeat = 2; 35 i++; 36 while (i < N && a[i] == a[i - 1]) { 37 repeat++; 38 i++; 39 } 40 smlTimes += repeat * (repeat - 1) / 2; 41 } 42 } 43 44 45 if (a[0] == a[N - 1]) { 46 lagTimes = smlTimes; 47 } else { 48 int i = 0, j = N - 1; 49 int endRepeat=1, startRepeat=1; 50 if (a[j] == a[j - 1]) { 51 endRepeat = 2; 52 j--; 53 54 while (j > 0 && a[j] == a[j - 1]) { 55 endRepeat++; 56 j--; 57 } 58 } 59 60 if (a[i] == a[i + 1]) { 61 startRepeat = 2; 62 i++; 63 64 while (i < N - 1 && a[i] == a[i + 1]) { 65 startRepeat++; 66 i++; 67 } 68 } 69 70 lagTimes = startRepeat * endRepeat; 71 } 72 73 System.out.println(smlTimes + " " + lagTimes); 74 } 75 } 76 77 78 }