之前準備把騰訊實習生招聘的第三道題做出來的,但是時間很緊,最終拖到今天才完成的,下午做了一個小時才弄出來的,主要是細節方面的問題。
這個題意思很簡單吧,給出很多數,找出“二元組”裏面差最小的和差最大的個數(兩個數的差事大的減去小的,也就是絕對值的意思)。說實話,這個題的處理確實很難把握。
我的解題思路是:先將這個數組排序,然後就很容易計算出差最大的二元組的個數,接下來就是計算最小二元組的個數。
- 最大二元組的計算是分別計算出最大值和最小值(可能存在重複,需要把握住),假設最小值的個數爲n,最大值的個數爲m,那麼差最大的二元組的個數即爲:n*m,若是不明白
- 最小二元組的計算則相對複雜一些,但是排序以後,最小差距的計算就是計算相鄰兩個數的差。其中需要把握的東西就是計算過程中”差距“由一個值變爲另一個值的時候需要好好把握,這個時候很容易出錯。我按照我寫的代碼來講述,大家可以根據我所說的自己再設計代碼,主要是一些細節的變化。還需要注意的一點就是,最小差並不一定是連續的,可能會間隔一些,我給個例子,大家對照着看看吧。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Solution(vector<int>& V){
int sz = V.size();
int min = 0;
int minNum = 0;//最小二元組數目
int maxNum = 0;//最大二元組數目
if (sz == 0){
cout << 0 << " " << 0 << endl; //差最小,差最大
return;
}
else if (sz == 1){
cout << 1 << " " << 1 << endl;
}
else{
sort(V.begin(), V.end()); //排序
int i = 0;
int j = sz - 1;
while (V[i] == V[i + 1] && i < sz - 1){
++i;
}
while (V[j] == V[j - 1] && j > 0){
--j;
}
maxNum = (i + 1)*(sz - j); //差最大的數
min = V[sz - 1] - V[0] + 1;
int flag = 0;
for (int k = 0; k < sz - 1; ++k)
{
if (V[k + 1] - V[k] < min){
min = V[k + 1] - V[k];
minNum = 1;
flag = 1; //主要用於記錄差距第一次變爲0
if (min == 0)
{
--k; //這樣做的目的是爲了不錯過min=0的,第一次統計的時候會少統計一個
}
}
else if (V[k + 1] - V[k] == min){
int sum = 0;
while (k< sz -1 && V[k + 1] - V[k] == min)
{
++k;
++sum;
}
if (min == 0){ //差距爲0
if (flag == 1){
minNum = (sum)*(sum + 1) / 2; //差距一次變爲0的時候需要好好注意
flag = 0;
}
else{
minNum += sum*(sum + 1) / 2;//根據相同元素個數計算二元組個數
}
}
else{ //差距不爲0
minNum += sum;
--k; //k會加兩次(for循環也會加一次,所以需要調整一下)
}
}
}
}
cout << minNum << " " << maxNum << endl;
}
int main()
{
int n;
int tmp;
while (cin >> n){
vector<int> arr;
for (int i = 0; i< n; ++i){
cin >> tmp;
arr.push_back(tmp);
}
Solution(arr);
}
return 0;
}