1. 程式人生 > >演算法快學筆記(一):演算法入門

演算法快學筆記(一):演算法入門

1. 演算法的定義

“演算法”一詞在不同的書籍以及網站上可能會存在一些差異,但是下面的定義個人覺得最為貼切:

1. 演算法代表著用系統的方法描述解決問題的策略機制
2. 能夠對一定規範的輸入,在有限時間內獲得所要求的輸出
3. 一個演算法的優劣可以用空間複雜度與時間複雜度來衡量

2. 論優秀演算法的重要性

在很多場景下,資料規模越大,越能體現優秀演算法的價值,接下來將以猜數遊戲為例進行說明優秀演算法的重要性。

假設 A隨便想了一個1到100中的某個數字讓B猜,B可以有兩種方案:

  1. 簡單查詢:從1開始猜,一直猜到A想的數字為止。
  2. 二分查詢:一半一半的猜,先猜50,如果小了,這時候就排除了1-50的數字!。接下來,你猜75,如果大了,就排除了75-100。以此類推。

接下來對兩種方式進行說明與比較

2.1 簡單查詢

該方法的優點是簡單,只需要從1一個個的猜,就一定能猜到。但是如果猜測數字的範圍非常的大,且猜的數字非常靠後,將會使用較多的時間。

2.2 二分查詢

二分查詢是一種演算法,其輸入是必須是一個有序的元素列表。每次猜都從列的中間元素開始,如果大了,就過濾掉比猜測值小的那一半數字,反之亦然。

實現程式碼如下:

// 使用二分查詢法,在有序列表intList中查詢target,返回對應的索引
func BinarySearch(intList []int, target int) int {
	start := 0
	end := len(intList) - 1
	for {
		if end <= start {
			break
		}
		mid := int((start + end) / 2)
		if intList[mid] == target {
			return mid
		}
		// 如果mid處的值大於目標值,就在mid之前的資料中搜索
		if intList[mid] > target {
			end = mid-1
		}
		// 如果mid處的值大於目標值,就在mid之後的資料中搜索
		if intList[mid] < target {
			start = mid+1
		}
	}
	return -1
}

2.3 簡單查詢VS二分查詢

如果列表包含100個數字,簡單查詢的方式可能要找100次才能找到結果,而二分查詢法由於每次查詢都會過濾掉一半的資料,因此最多隻需要7次(log100)就能找到結果。這個級別的資料,結果看起來差距還不是很大。

如果列表包含40億個數字,簡單查詢的方式可能要找40億次才能找到結果,而二分查詢法最多隻需要32次(log40億)就能找到結果。這個級別的資料,差距就比較可觀了。

假設B一秒鐘能猜10個數字,通過簡單查詢要猜4629(40億/10 秒)天,而通過二分查詢只需要4秒(log40億/10 秒)。

有上面的例子可以看出,一個優秀的演算法是多麼的重要!

注意:log指的都是log2

大O表示法

大O表示法指出了演算法有多快(O為運算元:Operations)。例如,假設列表包含n個元素。簡
單查詢需要檢查每個元素,因此需要執行n次操作,使用大O表示法,
這個執行時間為O(n)。二分查詢需要執行log n次操作,使用大O表示法的執行時間為 O(log n)。

關於大O表示法有以下幾點需要注意:

  1. 大O表示法讓你能夠比較運算元,它指出了演算法執行時間的增速,代表隨著資料集的增加,演算法所需時間的變化趨勢。
  2. 大 O 表示法指出了最糟情況下的執行時間

下面按從快到慢的順序列出了常見的5種大O執行時間:

  • O(log n),也叫對數時間,這樣的演算法包括二分查詢。
  • O(n),也叫線性時間,這樣的演算法包括簡單查詢。
  • O(n * log n),這樣的演算法包括快速排序(一種非常快的排序演算法)
  • O(n^2),這樣的演算法包括選擇排序(一種非常慢的排序演算法)。
  • O(n!),這樣的演算法包旅行商問題的解決方案-一種非常慢的演算法。

總結

  • 二分查詢的速度比簡單查詢快得多。
  • O(log n)比O(n)快。需要搜尋的元素越多,前者比後者就快得越多。
  • 演算法執行時間是從其增速的角度度量的。
  • 演算法執行時間用大O表示法表示。