小Q今天在上廁所時想到了這個問題:有n個數,兩兩組成二元組,差最小的有多少對呢?差最大呢?
輸入例子:
6
45 12 45 32 5 6
輸出例子:
1 2
思路:先排序,分一般情況和特殊情況,
特殊情況數組所有元素相同,差最小最大的組合個數都是C(n,2)
否則,差最大的組合個數 = 最小值個數MinNum * 最大值個數MaxNum
接下來求 ,差最小(minVal )的組合個數,
(1)若最小差爲0,那麼統計不同的重複元素的個數,我這裏寫的roo是後面出現相同元素的個數,所以roo=1的意思是後續數組只有1個與當前值相同的元素,就是C(2,2),通用公式是C(roo+1,2)
(2)最小差不爲0,那麼用 map 統計後續數組與當前值能構成最小差的元素的個數roo,直接加
//O(n+nlogn)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 100050;
typedef long long int ll;
int a[maxn];
map<int,int> ma;
int main()
{
// freopen("in.txt",stdin,"r");
// freopen("out.txt",stdout,"w");
int n;
while(scanf("%d",&n)!=EOF)
{
ma.clear();
for(int i=0;i<n;++i)scanf("%d",&a[i]);
sort(a,a+n);
if(a[0] == a[n-1]){
ll ans = n;
if(ans > 1)ans = ans * (ans-1)/2;
else ans = 0;// n == 1
printf("%lld %lld\n",ans,ans);
}
else{
ll MinNum = 0,MaxNum = 1,minVal = 2e11;
for(int i = 0;i < n - 1;++i)
{
if(a[i]==a[0])MinNum++;
if(a[i]==a[n-1])MaxNum++;
if(minVal > a[i+1]-a[i]) minVal = a[i+1] - a[i];
ma[a[i]]++;
}
ll MinAns = 0,roo = 0;
if(minVal == 0){
for(int i=0;i<n-1;++i)
{
if(a[i]==a[i+1])roo++;
else {
if(roo>0){
MinAns = MinAns + roo * (roo+1) / 2;
roo = 0;
}
}
}
if(roo>0){
MinAns = MinAns + roo * (roo+1) / 2;
roo = 0;
}
}
else {
for(int i = 0;i < n;++i){
roo = ma[a[i]+(int)minVal];
if(roo > 0) MinAns += roo;
}
}
printf("%lld %lld\n",MinAns,MinNum * MaxNum);
}
}
return 0;
}