[經典面試題]排序數組中絕對值最小元素,數組絕對值
【題目】
題目為: 有一個已經排序的數組(升序),數組中可能有正數、負數或0,求數組中元素的絕對值最小的數,要求,不能用順序比較的方法(複雜度需要小於O(n)),可以使用任何語言實現 例如,數組{-20,-13,-4, 6, 77,200} ,絕對值最小的是-4。 |
【分析】
給定數組是已經排好序的,且是升序,沒有重複元素。
一個簡單的思路,就是一次性遍曆數組,求出數組的元素的絕對值的最小值,這樣的時間複雜度為O(n)。
但是,這樣就浪費了題目的一個條件:數組是已經排好序的。所以,需要對原來的題目進行轉換。考慮到數組有序,利用二分尋找原理。
求數組中絕對值最小的元素,與0離得最近絕對值越小。基於這個原理設計代碼。
分三種情況:
(1)如果全是正數,返回第一個元素值。if(A[0] >= 0)
(2)如果全是負數,返回最後一個元素值。if(A[n-1] <= 0)
(3)有正有負,利用二分尋找找到0的插入位置,如果正好找到0的位置,0就是絕對值最小的元素,
如果沒有找到0,插入位置的左右元素比較絕對值大小 ,返回較小者OK。
【代碼】
/********************************** 日期:2015-01-29* 作者:SJF0115* 題目: 排序數組中絕對值最小元素* 來源:百度* 部落格:**********************************/#include <iostream>#include <algorithm>using namespace std;int MinAbs(int A[],int n){ if(n == 1){ return A[0]; }//if // 只有正數 if(A[0] >= 0){ return A[0]; } // 只有負數 if(A[n-1] <= 0){ return A[n-1]; } // 找到0的插入位置 int target = 0; int left = 0,right = n - 1; int mid; while(left <= right){ mid = left + (right - left) / 2; // 中間元素等於目標 if(A[mid] == target){ return A[mid]; } // 目標在左半部分 else if(A[mid] > target){ right = mid - 1; } // 目標在右半部分 else{ left = mid + 1; } }//while // 絕對值最小 if(abs(A[left]) < abs(A[right])){ return A[left]; } return A[right];}int main(){ //int A[] = {-6,-5,-4,-3,-2,-1}; //int A[] = {-6,-5,-4,1,2,3}; //int A[] = {1,2,3,4,5,6}; int A[] = {-20,-13,-4,6,77,200}; int n = 6; cout<<MinAbs(A,n)<<endl;; return 0;}