csdn_spider/blog/ds19991999/原创-- 算法图解笔记.md

369 lines
6.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 原创
算法图解笔记
# 算法图解笔记
### 目录
## 算法简介
二分法查找,输入一个**有序列表**返回元素位置或null。<br/> 一般而言,<strong>对于包含n个元素的列表用二分法查找最多需要
l
o
g
2
n
log_2 n
log2n</strong>
```
def binary_search(list, item):
low = 0
high = len(list) - 1
while low &lt;= high:
mid = (low + high) // 2
if list[mid] == item:
return mid
elif list[mid] &gt; item:
high = mid - 1
else:
low = mid + 1
return None
```
[binary_search.py](binary_search.py)
## 选择排序
由于数组的结构在内存中是连续的,添加新元素十分麻烦,链表的优势在于插入新元素;<br/> 数组的优势在于元素的随机访问。也就是说**数组和链表在插入和读取元素的时间复杂度刚好互补**。<br/> [selectSort](selectSort.py)
```
def findSmallest(arr):
smallest = arr[0]
smallest_index = 0
for i in range(1,len(arr)):
if arr[i] &lt; smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
def selectSort(arr):
newArr = []
for i in xrange(len(arr)):
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
```
我的写法
```
def selectSort2(arr):
n = len(arr)
for i in range(n):
for j in range(i, n):
if arr[j] &lt; arr[i]:
arr[i], arr[j] = arr[j], arr[i]
return arr
```
时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
## 递归
>
递归函数要有基线条件和递归条件,否则会无限循环.
看一个阶乘函数的实现:
```
def fact(x):
if x == 1:return 1
else: return x*fact(x-1)
```
## 快速排序
快速排序是分而治之的策略[quickSort](quickSort.py)
### 分而治之
```
def quickSort(arr):
if len(arr)&lt;2:
return arr
else:
pivot = arr[0]
less = [i for i in arr[1:] if i &lt;= pivot]
greater = [i for i in arr[1:] if i &gt; pivot]
return quickSort(less)+[pivot]+quickSort(greater)
```
这么看来比严版快排好理解多了,严版是用两个指针和一个基准值将数组划分成两部分,可以说时间复杂度确实小了不少。
```
def quickSort2(arr, left, right):
if left&gt;=right:
return arr
low = left
high = right
key = arr[left]
while left &lt; right:
while left &lt; right and arr[right] &gt;= key:
right -= 1
arr[left] = arr[right]
while left &lt; right and arr[left] &lt;= key:
left += 1
arr[right] = arr[left]
arr[left] = key
quickSort2(arr, low, left-1)
quickSort2(arr, left+1, high)
return arr
```
## 散列表
散列函数将输入映射到数字。它必须是一致的它将不同的输入映射到不同的数字。Python实现了散列表的实现——字典。<br/> 散列表是提供DNS解析这种功能的方式之一。
一个简单的投票:
```
voted = {}
def check_voter(name):
if voted.get(name):
print "kick them out!"
else:
voted[name] = True
print "let them vote!"
```
将散列表用作缓存,缓存是一种常用的加速方式,缓存的数据则存储在散列表中。
```
cache = {}
def get_page(url):
if cache.get(url):
return cache[url]
else:
data = get_data_from_server(url)
cache[url] = data
return data
```
冲突的解决方法:将两个键映射到同一个位置,就在这个位置存储一个链表。为避免冲突,需要好的散列函数和较低的填充因子。
填装因子=散列表包含的元素数/位置总数一旦填充因子大于0.7,就开始调整撒列表长度。
在平均条件下,散列表的时间复杂度为
O
(
1
)
O(1)
O(1),在最糟糕的情况下,时间复杂度为
O
(
n
)
O(n)
O(n)
## 广度优先搜索
图由节点——边组成。可以通过散列表将节点映射到其所有邻居,散列表是无序的。
```
graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["alice"] = ["peggy", "anuj"]
...
```
创建一个队列,用于存储要检查的人,从队列中弹出一个人,检查他是否是芒果销售商,否的坏将这个人所有的另据加入队列。
```
from collections import deque
search_deque = deque()
search_deque += graph["you"]
def person_is_seller(name):
return name[-1] == "m"
while search_deque:
person = search_deque.popleft()
if person_is_seller(persson):
return True
else:
search_deque += graph[person]
return False
```
但是这种方法有缺陷,检查会有重复。应该检查完一个人,就将其标记。
```
def search(name):
search_queue = deque()
search_queue += graph[name]
searched = []
while search_queue:
person = search_queue.popleft()
if not person in searched:
if person_is_seller(persson):
return True
else:
search_queue += graph[person]
searched.append(person)
return False
```
时间复杂度为
O
(
V
+
E
)
O(V+E)
O(V+E)边数和人数
## 狄克斯特拉算法
```
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost &lt; lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
```
## 贪婪算法
就是每步都选择最优解,最终得到全局的最优解。
### NP完全问题
## 动态规划
与上一章对应,贪婪算法得到的可能不是最优解,而动态规划可以得到最优解。动态规划先解决子问题,再逐步解决大问题。