1. 程式人生 > >二分查找的遞歸和非遞歸寫法

二分查找的遞歸和非遞歸寫法

int arch 時間 可能 class amp 二分查找 while 提高

一、概述

二分查找是針對有序數列的,對無序數列是無效的,在有序序列中使用二分查找能大大提高查找效率,通常能將時間按復雜度從O(n)降至O(logn)。

二、查找某數的位置(或存在性)

遞歸:

 1 //返回"-1"表示為找到
 2 //否則返回目標的下標(若有多個,只是其中一個)
 3 int binary_searchs(int *arr, int target, int l, int r)
 4 {
 5     if (l > r)  return -1;            
 6     int mid = (l + r) >> 1;
 7     if (arr[mid] == target) 
8 return mid; 9 else if (arr[mid] > target) 10 binary_search(arr, target, l, mid - 1); 11 else 12 binary_search(arr, target, mid + 1, r); 13 }

非遞歸:

 1 //返回"-1"表示為找到
 2 //否則返回目標的下標(若有多個,只是其中一個)
 3 int binary_searchs(int * arr, int x, int l, int r)
 4 {
 5     int lt = l, rt = r;
6 while (lt <= rt) 7 { 8 int mid = (lt + rt) >> 1; 9 if (arr[mid] == x) return mid; 10 else if (arr[mid] < x) 11 lt = mid + 1; 12 else 13 rt = mid - 1; 14 } 15 return -1; 16 }

三、查找某數出現的次數

遞歸:

 1 //返回target的出現次數
 2
//返回0意味著不存在 3 int binary_search(int *arr, int target, int l, int r) 4 { 5 if (l > r) return 0; 6 int mid = (l + r) >> 1; 7 if (arr[mid] == target) 8 return 1 + binary_search(arr, target, l, mid - 1) + binary_search(arr, target, mid + 1, r); 9 else if (arr[mid] > target) 10 binary_search(arr, target, l, mid - 1); 11 else 12 binary_search(arr, target, mid + 1, r); 13 }

遞歸(優化版):如果有序數列中,目標元素占大多數,二分法會退化成逐一遍歷,O(logn)增至O(n),我們要預防這種情況,所以當找到目標元素時,盡可能向兩邊去找目標元素。

 1 //返回target的出現次數
 2 //返回0意味著不存在
 3 int binary_search(int *arr, int target, int l, int r)
 4 {
 5     if (l > r)  return 0;
 6     int mid = (l + r) >> 1;
 7     if (arr[mid] == target)
 8     {
 9         int cnt1, cnt2;
10         cnt1 = cnt2 = mid;
11         if (((cnt1 - 1) >= l) && (arr[cnt1] == arr[cnt1 - 1]))  cnt1--;
12         if (((cnt2 + 1) <= r) && (arr[cnt2] == arr[cnt2 + 1]))  cnt2++;
13         return 1 + (cnt2 -cnt1) + binary_search(arr, target, l, cnt1 - 1) + binary_search(arr, target, cnt2 + 1, r);
14     }
15     else if (arr[mid] > target)
16         binary_search(arr, target, l, mid - 1);
17     else
18         binary_search(arr, target, mid + 1, r);
19 }

非遞歸:我覺得這個非遞歸不好寫,主要是找到目標元素時,在前一部分和後一部分也有可能存在目標元素,不用遞歸的方式不好寫。以後寫出來了再來補吧。

二分查找的遞歸和非遞歸寫法