1. 程式人生 > >改寫二分搜尋演算法

改寫二分搜尋演算法

一、實踐題目

改寫二分搜尋演算法

二、問題描述

設a[0:n-1]是已排好序的陣列,請改寫二分搜尋演算法,使得當x不在陣列中時,返回小於x的最大元素位置i和大於x的最小元素位置j。當搜尋元素在陣列中時,i和j相同,均為x在陣列中的位置。

輸入格式:

輸入有兩行:

第一行是n值和x值; 第二行是n個不相同的整陣列成的非降序序列,每個整數之間以空格分隔。

輸出格式:

輸出小於x的最大元素的最大下標i和大於x的最小元素的最小下標j。當搜尋元素在陣列中時,i和j相同。 提示:若x小於全部數值,則輸出:-1 0 若x大於全部數值,則輸出:n-1的值 n的值

輸入樣例:

在這裡給出一組輸入。例如:

6 5
2 4 6 8 10 12

輸出樣例:

在這裡給出相應的輸出。例如:

1 2

三、演算法描述

我們原來的二分查詢演算法BiSearch(int array [ ], int n, int key)尋找的是在序列(array)中存在的某個數(key),為了達到這一目的,我們需要定義左右兩個指標(left和right),如果找不到,最後的指標將會是 left > right ,根據題目要求,實際就是在二分搜尋的基礎上增加若尋找不到目標元素,返回 left 指標與 right 指標所指向的元素下標。要注意最後找不到時left指向的是大於查詢目標key的最小下標。

綜上,在查詢過程中,若查詢到目標元素,則直接輸出兩次mid,結束查詢,否則,則在查詢完畢後,分別輸出right 與 left指標指向的下標

四、演算法分析

  時間複雜度:二分查詢是將陣列 array 從中間切成大致相等的兩部分,取 array[n/2] 與key做比較,如果 target=a[n/2] ,則找到 key 。因為每次規模都小一半,我們可以假設查找了 k 次,則 2^k = n,所以 k = log n,所以時間複雜度為O(log n)。

  空間複雜度:本題採用的是非遞迴的做法,而且變數不會隨著 n 而變化,所以空間複雜度為O(1)。

五、心得體會

之前一直以為二分查詢就十分簡單,後來才發現原來有這麼多的變通,不過在理解好最高根本的二分思想之後,也就都迎刃而解了。在做這道題的過程一開始理所當然以為left就是小於key的最大元素下標,後來人肉cpu跑了一遍才發現並不是。所以對於一些不理解的演算法,我認為自己跟著演算法一步一步算一遍有助於更好地理解演算法。