1. 程式人生 > 實用技巧 >二分法

二分法

二分法的時間複雜度是O(logn),所以在演算法中,比O(n)更優的時間複雜度幾乎只能是O(logn)的二分法。

根據時間複雜渡來倒推演算法也是面試中的常用策略:題目中若要求演算法的時間複雜度是O(logn),那麼這個演算法基本上就是二分法。

在這裡,我們不做二分法的基本概念介紹,直接給出實現二分最基本的程式碼。具體理由看註釋。

在這裡特別說明:

在二分法中的while迴圈只是用於縮小查詢範圍,直至縮小到我們能夠直接可辯別的範圍內。而最後結果的return是依靠最後的if語句來比較並實現的。

  1 class solution{
  2 
  3     public:
  4         int
binarySearch(int nums[], int target) 5 { 6 //判斷傳入的陣列不為空 7 if(nums == NULL || sizeof(nums) / sizeof(int) == 0) 8 { 9 return -1; 10 } 11 12 int len = sizeof(nums) / sizeof(int); 13 int
start = 0; 14 int end = len - 1; 15 16 17 //這裡判斷條件是start + 1< end 18 //終止時是start + 1 = end; 19 //這樣終止時是start和end是相鄰的兩個下標。 20 21 //注意:我們並沒有在while語句裡面直接得到並return 22 //while只是縮小了區間範圍 23 //而是把範圍縮小到了我們易於操作的兩個索引的範圍內,
24 //並且通過後面的if語句來判斷並return 25 while(start + 1 < end) 26 { 27 //這裡沒有采用middli = (start + end) / 2; 28 //原因是避免當start和end很大的時候形成溢位 29 int middle = start + (start - end) / 2; 30 31 if(nums[midddle] == target) 32 { 33 middle = end; 34 } 35 else if(nums[middle] < target) 36 { 37 start = middle + 1; 38 } 39 40 else 41 { 42 end = middle - 1; 43 } 44 45 } 46 47 if(nums[start] == target) 48 { 49 return start; 50 } 51 if(nums[end] == target) 52 { 53 return end; 54 } 55 else 56 { 57 return -1; 58 } 59 60 61 } 62 63 int binarySearch_v2(int nums[], int target) 64 { 65 if(nums == NULL || sizeof(nums) / sizeof(int) == 0) 66 { 67 return -1; 68 } 69 70 int len = sizeof(nums) / sizeof(int); 71 int start = 0; 72 int end = len - 1; 73 74 //這裡判斷語句是start < end; 75 //跳出迴圈時start = end 76 //所以在後面的if語句判斷中只有nums[start] == target 77 78 //因為int middle = start + (start - end) / 2具有向左靠攏的性質 79 //所以這裡的更新條件為start = middle + 1, end = middle - 1 80 while(start < end) 81 { 82 int middle = start + (start - end) / 2; 83 84 if(nums[middle] == target) 85 { 86 start = middle; 87 } 88 else if(nums[middle] < target) 89 { 90 start = middle + 1; 91 } 92 else: 93 { 94 end = middle - 1; 95 } 96 } 97 98 if(nums[start] = target) 99 { 100 return start; 101 } 102 else: 103 { 104 return -1; 105 } 106 107 108 } 109 }

二,二分位置之OOXX

在這種題目中,可以將OO視為不滿足某個條件,而將XX視為滿足某個條件,這樣就可以把一個數組或者序列分為OO....OOXX....XX型別。而這樣的題目往往是給出一個數組,要求找出陣列中第一個/最後一個滿足條件的位置。

OOOOO....OOOXXX...XXXXX

對於這樣的題目可以採用二分法進行。

三:在一個經過排序的陣列元素超級多的陣列中找出目標元素。

解決這樣的問題,方式一:暴力求解,直接按順序去除陣列中元素與目標值target進行比較,這樣的演算法的時間複雜度是O(n),當然,在生活中也是不願意看到的。方式二:二分法求解。

我們先來說明c++中vector的實現原理,然後將這樣的原理移植到我們的二分演算法中。