天天看點

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

作者:和貓妹學Python

小朋友們好,大朋友們好!

我是貓妹,一名愛上Python程式設計的國小生。

歡迎和貓妹一起,趣味學Python。

今日主題

貓妹最近不是在學習《人工智能程式設計實踐Python5級》嗎?

這裡面除了基本的Python知識外,還有幾章是介紹算法的。

算法,對貓妹來說是陌生的,畢竟剛接觸嘛!

但是,算法在計算機中是非常重要的,可以說是人類智慧的結晶。

是以呢,這些很重要很基礎的算法,貓妹決定簡單記錄下。

還記得高斯小時候的故事嗎?

求計算1+2+。。。+100的和。

如果一個一個加,當然可以,但容易出錯,而且非常耗費時間。

如果按照高斯的方法呢?

簡單,而且不容易出錯。

這就是算法,同一個問題,不同的解題思路。

有的算法效率高,有的算法效率低。

有的算法容易了解,有的算法思路實在是高。

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)
真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)
真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

貓爸小時候,還是個國小生,90年代。

有一次臨近春節,他的玩伴和他做了一個遊戲,讓他心中藏一個數字,1000之内的整數。

他隻問幾個問題,貓爸隻需要回答是或者不是,他就能猜出數字。

貓爸一開始覺得不可能,但是他的好友的确幾次都猜對了。

貓爸覺得挺神奇的,但是不知道咋回事。

他的問題就是将數的範圍逐漸縮小,每次縮小一半,也每次靠近貓爸心中的那個數。

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

這其實就是諸葛亮猜數字的故事。

諸葛亮召集将士,讓他們從1-1024中選出一個整數記在心裡。然後諸葛亮會問他們10個問題,他們隻需回答:“是”或“不是”,最終諸葛亮就能得出他們心中所想的數。

如問一謀士:“你選的數大于512?”謀士答:“不是”,之後9個問題過後,諸葛亮得出謀士所選的數是1,謀士大為吃驚,這的确是他想的數。

方法就是把1024一半一半地取,取到第十次時就是1。根據這個原理去提10個問題就能找到别人心中所想的數。

這裡面蘊含的算法就是二分法。

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

什麼是二分法

二分法是一種計算機算法,也稱為折半搜尋或者二分搜尋法。

它是一種在有序集合中查找特定值的算法。

該算法是通過将有序集合不斷地二分為兩半來實作的,進而查找到所需的元素。

簡而言之,它是一種減少搜尋區域的方法,進而使得搜尋時間更快。

二分法思想

二分法是一種高效的搜尋算法,适用于有序資料集的查找。

二分法的思想是不斷将搜尋區域二分為兩個部分,直到找到目标元素或者搜尋區域為空。

其基本思想是将待查找區間不斷縮小一半,直到找到目标元素或者确定目标元素不存在。

具體步驟如下:

1)首先,找到清單的中間元素。

2)如果中間元素是目标元素,則停止搜尋。

3)如果目标元素比中間元素小,則在中間元素的左邊繼續搜尋。

4)如果目标元素比中間元素大,則在中間元素的右邊繼續搜尋。

5)重複以上步驟,直到找到目标元素或者搜尋區域為空。

二分法的時間複雜度

二分查找對有序清單的時間複雜度是 O(log n),其中 n 是清單的長度。

相對于線性搜尋,二分查找效率更高,特别是當搜尋區域比較大的時候。

二分法舉例

Python語言非常适合實作二分法算法,其實作代碼非常簡單。

參考程式如下:

def binary_search(arr, low, high, target):
    if high >= low:
        mid = (high + low) // 2


        #如果目标元素等于中間元素,則找到了目标元素
        if arr[mid] == target:
            return mid
        #如果目标元素比中間元素小,則在左邊繼續查找
        elif arr[mid] > target:
            return binary_search(arr, low, mid - 1, target)
        #如果目标元素比中間元素大,則在右邊繼續查找
        else:
            return binary_search(arr, mid + 1, high, target)


    else:#元素不存在于數組中
        return -1


if __name__ == '__main__':
    arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    target = 5
    result = binary_search(arr, 0, len(arr)-1, target)
    if result != -1:
        print(f"元素在索引為 {result} 的位置")
    else:
        print("元素不在數組中")

           

我們首先定義一個`binary_search()`函數,該函數采用遞歸的方式實作二分查找。

參數`arr`是一個有序數組,參數`low`和參數`high`是數組中的兩個索引,分别表示最低索引和最高索引。

參數`target`是要查找的元素。

在`binary_search()`函數中,先判斷是否達到基準情況(即`high >= low`),如果已經到達基準情況,再判斷目标元素是否等于中間元素(這裡的中間元素是通過`mid`索引獲得的)。如果目标元素等于中間元素,則傳回中間元素的索引。

如果目标元素比中間元素小,則遞歸地查找左半邊。

如果目标元素比中間元素大,則遞歸地查找右半邊。

最後,我們以一個有序數組`arr`和要查找的元素`target`調用`binary_search()`函數。

如果函數傳回的結果不為-1,則說明目标元素在數組中,列印該元素的索引值;否則,列印該元素不存在數組中。

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

我們可以看到,對于有序數組,二分查找比線性查找具有更好的時間複雜度。

當數組規模較大時,二分查找的時間複雜度更比線性查找的時間複雜度快很多。

在實際開發中,如果要在一個有序數組或清單中查找元素,應優先考慮使用二分查找算法。

真不愧是神算諸葛亮啊,猜數字背後竟然蘊含着這麼神奇的算法(40)

好了,我們今天就學到這裡吧!

如果遇到什麼問題,咱們多多交流,共同解決。

我是貓妹,咱們下次見!