An algorithm is an effective method that can be expressed within a finite amount of space and time and in a well-defined formal language for calculating a function.算法是在一個明肯定義的標準語言裏在有限空間與時間內計算函數的有效方法。node
猜數字遊戲的二分查找代碼:git
def binary_search(list, item):
# low and high keep track of which part of the list you'll search in.
low = 0
high = len(list) - 1
# While you haven't narrowed it down to one element ...
while low <= high:
# ... check the middle element
mid = (low + high) // 2
guess = list[mid]
# Found the item.
if guess == item:
return mid
# The guess was too high.
if guess > item:
high = mid - 1
# The guess was too low.
else:
low = mid + 1
# Item doesn't exist
return None
my_list = [1, 3, 5, 7, 9]
print binary_search(my_list, 3) # => 1
# 'None' means nil in Python. We use to indicate that the item wasn't found.
print binary_search(my_list, -1) # => None
複製代碼
一些常見的大O運行時間算法
一些結論:express
內存的工做原理: 將數據存入內存時,請求計算機提供存儲空間,計算機給你一存儲地址。當存儲多項數據時,有數組和鏈表兩種存儲方式。數組
數組 | 鏈表 | |
---|---|---|
讀取 | O(1) | O(n) |
插入 | O(n) | O(1) |
刪除 | O(n) | O(1) |
注意: 僅當可以當即訪問要刪除的元素時,刪除操做的運行時間才爲O(1)。一般咱們都記錄了鏈表的首尾元素。緩存
# Finds the smallest value in an array
def findSmallest(arr):
# Stores the smallest value
smallest = arr[0]
# Stores the index of the smallest value
smallest_index = 0
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
# Sort array
def selectionSort(arr):
newArr = []
for i in range(len(arr)):
# Finds the smallest element in the array and adds it to the new array
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
print selectionSort([5, 3, 6, 2, 10]) #[2, 3, 5, 6, 10]
複製代碼
若是使用循環,程序的性能可能更高;若是使用遞歸,程序可能更容易理解。bash
# recursive count
def count(list):
if list == []:
return 0
return 1 + count(list[1:])
# recursive max
def max(list):
if len(list) == 2:
return list[0] if list[0] > list[1] else list[1]
sub_max = max(list[1:])
return list[0] if list[0] > sub_max else sub_max
# factorial
def fact(x):
if x == 1:
return 1
else:
return x * fact(x-1)
print fact(5)
複製代碼
D & C(divide and Conquer):分而治之,一種遞歸式問題解決方案,快速排序就是很好的🌰。數據結構
def quicksort(array):
if len(array) < 2:
# base case, arrays with 0 or 1 element are already "sorted"
return array
else:
# recursive case
pivot = array[0]
# sub-array of all the elements less than the pivot
less = [i for i in array[1:] if i <= pivot]
# sub-array of all the elements greater than the pivot
greater = [i for i in array[1:] if i > pivot]
return quicksort(less) + [pivot] + quicksort(greater)
print quicksort([10, 5, 2, 3])
複製代碼
voted = {}
def check_voter(name):
if voted.get(name):
print "kick them out!"
else:
voted[name] = True
print "let them vote!"
check_voter("tom")
check_voter("mike")
check_voter("mike")
複製代碼
from collections import deque
def person_is_seller(name):
return name[-1] == 'm'
graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["claire"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []
def search(name):
search_queue = deque()
search_queue += graph[name]
# This array is how you keep track of which people you've searched before.
searched = []
while search_queue:
person = search_queue.popleft()
# Only search this person if you haven't already searched them.
if not person in searched:
if person_is_seller(person):
print person + " is a mango seller!"
return True
else:
search_queue += graph[person]
# Marks this person as searched
searched.append(person)
return False
search("you")
複製代碼
廣度優先搜索,找出的是段數最少的路徑,但不必定是最快但路徑。而Dijkstra’s algorithm就是解決找出最快路徑但問題。app
四個步驟:less
權重:該算法每條邊都有關聯數字的圖。
(非)加權圖((un)weight graph):(不)帶權重的圖。計算非加權圖的最短路徑用廣度優先算法,計算加權圖最短路徑用狄克斯特拉算法。
示例:
# the graph
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
graph["fin"] = {}
# the costs table
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = infinity
# the parents table
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None
processed = []
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
# Go through each node.
for node in costs:
cost = costs[node]
# If it's the lowest cost so far and hasn't been processed yet...
if cost < lowest_cost and node not in processed:
# ... set it as the new lowest-cost node.
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
# Find the lowest-cost node that you haven't processed yet.
node = find_lowest_cost_node(costs)
# If you've processed all the nodes, this while loop is done.
while node is not None:
cost = costs[node]
# Go through all the neighbors of this node.
neighbors = graph[node]
for n in neighbors.keys():
new_cost = cost + neighbors[n]
# If it's cheaper to get to this neighbor by going through this node...
if costs[n] > new_cost:
# ... update the cost for this node.
costs[n] = new_cost
# This node becomes the new parent for this neighbor.
parents[n] = node
# Mark the node as processed.
processed.append(node)
# Find the next node to process, and loop.
node = find_lowest_cost_node(costs)
print "Cost from the start to each node:"
print costs
複製代碼
工做原理:先解決子問題,在逐步解決大問題。