1. 程式人生 > >尋找非遞減序列中絕對值最小值的絕對值

尋找非遞減序列中絕對值最小值的絕對值

return 可能 while 4.3 clu class ret size 相同

給定一個有序整數序列(非遞減序),可能包含負數,找出其中絕對值最小的元素,比如給定序列 -5、-3、-1、2、8 則返回1。
分析:由於給定序列是有序的,而這又是搜索問題,所以首先想到二分搜索法,只不過這個二分法比普通的二分法稍微麻煩點,可以分為下面幾種情況
如果給定的序列中所有的數都是正數,那麽數組的第一個元素即是結果。
如果給定的序列中所有的數都是負數,那麽數組的最後一個元素即是結果。
如果給定的序列中既有正數又有負數,那麽絕對值的最小值一定出現在正數和負數的分界處。
為什麽?因為對於負數序列來說,右側的數字比左側的數字絕對值小,如上面的-5、-3、-1,而對於整整數來說,左邊的數字絕對值小,比如上面的2、8,將這個思想用於二分搜索,可先判斷中間元素和兩側元素的符號,然後根據符號決定搜索區間,逐步縮小搜索區間,直到只剩下兩個元素。
單獨設置一個函數用來判斷兩個整數的符號是否相同

 1 /*
 2 給定一個有序整數序列(非遞減序),可能包含負數,找出其中絕對值最小的元素,比如給定序列 -5、-3、-1、2、8 則返回1。
 3 分析:由於給定序列是有序的,而這又是搜索問題,所以首先想到二分搜索法,只不過這個二分法比普通的二分法稍微麻煩點,可以分為下面幾種情況
 4     如果給定的序列中所有的數都是正數,那麽數組的第一個元素即是結果。
 5     如果給定的序列中所有的數都是負數,那麽數組的最後一個元素即是結果。
 6     如果給定的序列中既有正數又有負數,那麽絕對值的最小值一定出現在正數和負數的分界處。
 7 */
 8 #include <iostream>
 9
#include <cmath> 10 11 using namespace std; 12 13 bool sameSign(int m, int n) 14 { 15 if((m>>31) == (n>>31)) 16 return true; 17 else 18 return false; 19 } 20 21 //找出一個非遞減證書序列中絕對值最小的數 22 int getMinNumberAbsoluteValue(int *arr, int n) 23 { 24 if(n == 1) 25
return arr[n]; 26 if(sameSign(arr[0], arr[n-1])) 27 return arr[0] >= 0 ? arr[0] : abs(arr[n-1]); 28 29 //二分搜索 30 int mid, low = 0, high = n-1; 31 while(low < high) 32 { 33 if(low + 1 == high) 34 return abs(arr[low]) < abs(arr[high]) ? abs(arr[low]) : abs(arr[high]); 35 mid = (low + high) >> 1; 36 if(sameSign(arr[low], arr[mid])) 37 { 38 low = mid;//分界點就在mid處 39 continue; 40 } 41 if(sameSign(arr[high], arr[mid])) 42 { 43 high = mid; 44 continue; 45 } 46 } 47 return abs(arr[low]); 48 } 49 50 int main() 51 { 52 int arr[5] = {-5, -3, -1, 2, 7}; 53 54 cout << "arr中絕對值最小值的絕對值為:" << getMinNumberAbsoluteValue(arr, 5) << endl; 55 return 0; 56 }

尋找非遞減序列中絕對值最小值的絕對值