(面試題)求出兩兩之差絕對值最小的值

1.        有一個整數數組,請求出兩兩之差絕對值最小的值。記住,只要得出最小值即可,不需要求出是哪兩個數。(Microsoft) 

方法1:兩兩作差求絕對值,並取最小,O( n2 )。

方法2:排序,相鄰兩點作差求絕對值,並取最小,O( nlgn ).

方法3:有沒有O( n )的解法?(選擇網絡)

設數組A = { a1, a2, … , an }, 求 s = min( |ai - aj| ), 其中1<= i, j <=n.

設B = { b1, b2, … , bn-1 }, 且 bi = ai – ai+1

即:b1 = a1 – a2, b2 = a2 – a3, b3 = a3 – a4, …

 於是有如下規律:

例如:a3 – a5 = ( a3 – a4 ) + ( a4 – a5 ) =b3 + b4

a1 – a6 = b1 + b2 + … + b5

即:ai – aj = bi + … + bj-1

則數組A中任意兩個數的差,都可以用數組B中一個字段的和表示。

則原問題可以轉換爲:

在數組B中,求連續的某一段,使其和的絕對值最小。

例如 B = { 1, -2, 3, -1, -9, 7, -5, 6 };

則絕對值最小值爲0,具體是{ -2, 3, -1 } 或 {3, -1, -9, 7}

解到這邊,卡住了。。。



方法4:計數排序,相鄰兩點作差求絕對值,並取最小。

#include<iostream>
using namespace std;
int MinErrorSuquence(int* a,int length)
{
int bigest1=0;//記錄正數的最大值 
int bigest2=0;//記錄負數的最小值
        int Error=65536;//用於比較

for(int i=0;i<length;i++)//bigest1爲數組中最大的正數,bigest2爲最小的負數 
{
  if(a[i]>=0&&a[i]>bigest1) bigest1=a[i];
  if(a[i]<0&&a[i]<bigest2)  bigest2=a[i];
}

int timesOfNumber[bigest1-bigest2];//定義每個整數出現的次數,存放在數組裏面。。 
                                       //例如5出現2次,那麼a[5]=2    
for(int i=bigest2;i<=bigest1;i++)
{
timesOfNumber[i]=0;
}


for(int i=0;i<length;i++)
{
  
 int tmp=a[i];
      ++timesOfNumber[tmp];
  }
int index=0;

for(int i=bigest2;i<=bigest1;i++)//排序 
{
for(int j=0;j<timesOfNumber[i];j++)
{
a[index]=i;
++index;
}
}
for(int i=0;i<length-1;i++)//求差的最小值 
     {
   
   if(a[i+1]-a[i]<Error)
      Error=a[i+1]-a[i];
}
  return Error;


}
int main(void)
{
int a[9]={-2,-1,-6,5,-12,8,-4,-7,-3};
cout<<MinErrorSuquence(a,9)<<endl;
for(int i=0;i<9;i++)//重新排列後的數組
cout<<a[i]<<endl;

       return0;

}



解題後的幾點思考:

1:數組下標可以爲負整數,這個平時可能比較少注意到。一般情況下都是從0開始,在這邊比較特殊。

2:算法4遍歷的3次數組,第一次:取最大最小值。第二次,排序。第三次:相鄰兩項做差,比較。

    複雜度爲:O(n)? 還是O(3n)?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章