無論是參加面試還是筆試,數組都是常考的內容,並且考察數組的知識往往結合着比較有意思的算法。在這里參照網上的資料和平時看過的相關書籍總結一下,作為自己的面試復習材料吧。我知道這個總結肯定有遺漏或者是不對的地方,希望大家看到可以優化和改正的的地方,幫幫忙給點新思路吧。謝謝大家~~
1.求數組中的最大值(最小值)
問題描述:給定一個整數數組arr,找出其中的最大值(最小值)。
解決思路:傳統的方法就是遍歷一次數組即可得到最大值(最小值),時間復雜度是O(N);現在說另外一個思路利用二分,即將數組分成元素數目接近相等的兩部分,然后分別找到兩個部分的的最大值(最小值),最后合並,比較兩個部分的最大值(最小值),即可得到最終的最大值(最小值)。
代碼:

1 int FindMax(int *arr,int l,int r) 2 { 3 if(l == r) 4 { 5 return arr[l]; 6 } 7 int mid = (l+r)/2; 8 int LMAX,RMAX; 9 LMAX = FindMax(arr,l,mid); 10 RMAX = FindMax(arr,mid+1,r); 11 return max(LMAX,RMAX); 12 }
2.求數組中出現次數超過一半的元素
問題描述:整數數組arr中,一定存在一個數x,x在數組arr中出現的次數過半,請找出這個數x。
解決思路:既然x在數組中出現的個數過半,那么若將數組arr排序,顯然數組中arr[N/2]一定是要找的x(N數組arr中元素的個數)。這個思路的時間復雜度取決於排序算法的時間復雜度,因此整個算法的時間復雜度達到O(N*logN)是沒有問題的。既然x在數組arr中出現的次數過半,那么在遍歷數組的過程中若每次遇到與x不同的數,x出現的數目-1,出現x,則x出現的數目+1,那么到最后剩下的一定是x。這種情況下,只需要遍歷一次數組,時間復雜度是O(N),但是,難點是我們事先不知道x是什么,那么算法怎么實現呢?看看代碼就明白啦~~
代碼:

1 int Find(int *arr,int n) 2 { 3 int tmp = arr[0]; 4 int count = 1;//計數器 5 for(int i = 1 ; i < n ; i++) 6 { 7 if(count == 0) 8 { 9 tmp = arr[i]; 10 count = 1; 11 } 12 else if(tmp == arr[i]) 13 { 14 count++; 15 } 16 else 17 { 18 count--; 19 } 20 } 21 return tmp; 22 }
3.求數組中元素間的最近距離(一)
問題描述:數組arr[]中存在N個元素(數組中N個元素沒有范圍),找到這樣的a和b,使得abs(a,b)的值最小。
解決思路:這是個比較簡單的問題了,思路也很容易想到,只需要將arr進行排序,這時數組中元素的最短距離只可能是相鄰的兩個元素之間,這個算法的時間復雜度是:O(N*logN)。如果不對數組進行排序,那么就需要枚舉數組中的每兩個元素了,求出最小距離,時間復雜度是O(N*N)。
代碼:

1 int MinDistance(int *arr,int n) 2 { 3 int tmp_MIN = INF; 4 //假設INF是arr中兩個數相加能得到的最大值 5 sort(arr,arr+n); 6 for(int i = 0 ; i < n-1; i++) 7 { 8 if(arr[i+1] - arr[i] < tmp_MIN) 9 { 10 tmp_MIN = arr[i+1] - arr[i]; 11 } 12 } 13 return tmp_MIN; 14 }
4.求數組中元素間的最近距離(二)
問題描述:和上一個問題相似,區別是arr中的數組元素的取值范圍的。
解決思路:既然加了一個條件,那么看來就是利用這個條件進行優化了。既然數組中的元素有了范圍,不妨先假設數組中值在0~100之間,那么我們可以這樣做,申請一個數組bool fuzhu[100],這樣遍歷一遍數組,記錄arr中出現的元素,假設arr中包含4,那么arr[4]=1,然后在遍歷一遍fuzhu,fuzhu[i]值為1,表示i存在於arr中,這樣計算“相鄰”的fuzhu[]=1的元素,計算出最小距離。用一個大家看書時比較不願意看到的詞:經分析,時間復雜度是O(N+M),其中M是aar中元素的所在區間大小。
代碼:

1 int MinDistance(int *arr,int n) 2 { 3 bool fuzhu[101]; 4 int first,second; 5 int tmp_MIN = INF; 6 memset(fuzhu,false,sizeof(fuzhu)); 7 //遍歷找出在arr出現的數 8 for(int i = 0 ; i < n ; i++) 9 { 10 fuzhu[arr[i]] = true; 11 } 12 int j = 0; 13 while(j < 101 && !fuzhu[j]) 14 { 15 j++; 16 } 17 first = j++;//獲取fuzhu中第一個不為0的數 18 while(j < 101 && !fuzhu[j]) 19 { 20 j++; 21 } 22 second = j++;//獲取fuzhu中第二個不為0的數 23 while(1) 24 { 25 if(second - first < tmp_MIN) 26 { 27 tmp_MIN = second - first; 28 } 29 while(j < 101 && !fuzhu[j]) 30 { 31 j++; 32 } 33 if(j > 100) break; 34 first = second; 35 second = j++; 36 } 37 return tmp_MIN; 38 }
小結:大家看后,肯定會說arr中數組范圍也可能是負數啊,那怎么辦呢?注意了,這個題要求的是,最近距離。下標雖然不能為負,但是只要移位存儲就完事了嗎!畢竟只需要最小距離啊,平行移動不影響最小距離。比如arr中元素的范圍是-100~~100,那么只需要當出現-100,對應的fuzhu[-100+100] = fuzhu[0] = true。不就可以了嗎?
5.求兩個數組中的相同元素
問題描述:現在有兩個已經排好序的整數數組arr1和arr2,找出兩個數組中的相同元素。
解決思路:既然已經排好序了,那么問題就簡單了,假設arr1[2]和arr2[4]相等,那么搜索arr1[3]只需要和arr2中下標4及以后的元素比較。如果arr1和arr2中元素的個數分別是N和M,那么這個算法的時間復雜度是O(N+M),不妨先看看代碼。
代碼:

1 // 找出兩個數組的相同元素 2 void FindSame(int *arr1, int *arr2,int n,int m) 3 { 4 int i = 0; 5 int j = 0 ; 6 while (i < n && j < m) 7 { 8 if (arr1[i] < arr2[j]) 9 ++i; 10 else if(arr1[i] == arr2[j]) 11 { 12 cout<<arr1[i]<<endl; 13 ++i; 14 ++j; 15 } 16 else//arr1[i] > arr2[j] 17 ++j ; 18 } 19 }
小結:對於這個問題arr1和arr2數組都已經是排好序的,那么如果兩個數組都不是排好序的呢??后來在網上查了點資料,發現這樣一個哈希的思路:遍歷一遍arr1,建立哈希表,然后遍歷一遍arr2,看看哪一個元素存在於哈希表中。這樣一來時間復雜度還是O(N+M),但是多引入了O(N)的空間復雜度。在這里:求高手給出哈希的C++代碼!!!
學習中的一點總結,歡迎拍磚哦^^