《算法图解》简单学习 ^_^

二分查找

def binary_search(list, item):
    low = 0
    high = len(list) - 1

    while low <= high:
        mid = (low + high) // 2
        guess = list[mid]
        if guess == item:
            return mid
        if guess > item:
            high = mid - 1
        else:
            low = mid + 1
    return None

my_list = [1, 3, 5, 7, 9]
print(binary_search(my_list, 3)) # 1
print(binary_search(my_list, -1)) # None

选择排序

# 找出数组中最小元素的函数
def findSmallest(arr):
    smallest = arr[0]
    smallest_index = 0
    for i in range(1, len(arr)):
        if arr[i] < smallest:
            smallest = arr[i]
            smallest_index = i
    return smallest_index

# 排序算法
def selectionSort(arr):
    newArr = []
    for i in range(len(arr)):
        smallest = findSmallest(arr)
        newArr.append(arr.pop(smallest))
    return newArr

print(selectionSort([5, 3, 6, 2, 10]))
# [2, 3, 5, 6, 10]

递归

# 编写一个倒计时的函数
def countdown(i):
    print(i)
    if i <= 1:    # 基线条件(base case)指函数不再调用自己,从而避免形成无限循环
        return 
    else:   # 递归条件(recursive case)指函数调用自己
        countdown(i-1)

递归列表求和函数

# 编写求和函数
def sum_list(list):
    if list == []:
        return 0
    else:
        return list[0] + sum_list(list[1:])

print(sum_list([1, 2, 3, 4, 5, 6]))

查找列表最大元素函数

# 编写查找列表最大元素的函数
def findmax(list):
    if list[0] >= max(list[0:]):
        return list[0]
    else:
        return findmax(list[1:])

print(findmax([2, 5, 6, 1, 0, 9]))

快速排序

def quicksort(array):
    if len(array) < 2:
        return array
    else:
        pivot = array[0]
        less = [i for i in array[1:] if i <= pivot]
        greater = [i for i in array[1:] if i > pivot]
        return quicksort(less) + [pivot] + quicksort(greater)
    
print(quicksort([10, 5, 2, 3]))
# [2, 3, 5, 10]

广度优先搜索

解决最短路径问题(shortest-path problem)的算法被称为广度优先搜索(breadth-first search, BFS)。
节点(node)和(edge)组成。一个节点可能与众多节点直接相连,这些节点被称为邻居
图中的关系是单向的时候,即为有向图(directed graph);无向图(undirected graph)没有箭头,其中的关系是双向的,直接相连的节点互为邻居。无向图中,每条边都是一个环。
如果任务A依赖于任务B,在列表中任务A就必须在任务B后面,这被称为拓扑排序,使用它可以根据图创建一个有序列表。
树是一种特殊的图,没有往后指的边。
广度优先搜索可回答两类问题:
1- 从节点A出发,有前往节点B的路径吗?
2- 从节点A出发,前往节点B的哪条路径最短?

from collections import deque 
search_queue = deque()   # 创建一个队列
search_queue += graph["you"]  # 将你的邻居都加入到这个搜索队列中
searched = []  # 用于记录检查过的人

while search_queue:
    person = search_queue.popleft()   # 取出其中的第一个人
    if person not in searched:  # 仅当这个人没检查过时才检查
        if person_is_seller(person):
            print(person + " is a mango seller!")
            return True
        else:
            search_queue += graph[person]
            searched.append(person)  # 将这个人标记为检查过
return False

def person_is_seller(name):
    return name[-1] == 'm'

狄克斯特拉算法

狄克斯特拉算法(Dijkstra’s algorithm)可以找到有向无环图中的最短路径。加权图中每条边都有关联数字,称为权重(weight)。带权重的图称为加权图(weighted graph),不带权重的图称为非加权图(unweighted graph)。它包含4个步骤:
1- 找出“最便宜”的节点,即可在最短时间内前往的节点;
2- 对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销;
3- 重复这个过程,直到对图中的每个节点都这样做了;
4- 计算最终路径。
此处最短路径指的并不一定是物理距离,也可能是让某种度量指标最小。
如果出现负权边,即不能使用狄克斯特拉算法,得用贝尔曼-福德算法(Bellman-Ford algorithm)。

# 创建带权重的散列表
graph["start"] = {}
graph["start"]["a"] = 6
grpah["start"]["b"] = 2

graph["a"] = {}
graph["a"]["fin"] = 1

graph["b"] = {}
graph["b"]["a"] = 3
grpah["b"]["fin"] = 5

graph["fin"] = {}  # 终点没有任何邻居

# 创建开销表
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 3
costs["fin"] = infinity

# 存储父节点的散列表
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"]= None

# 数组,用于记录处理过的点
processed = []

node = find_lowest_cost_node(costs)  
# 在未处理的节点中找出开销最小的节点
while node is not None: # while循环在所有节点都被处理过后结束
    cost = costs[node]
    neighbors = graph[node]
    for n in neighbors.keys(): # 遍历当前节点的所有邻居
        new_cost = cost + neighbors[n]
        if costs[n] > new_cost: # 如果经当前节点前往该邻居更近
            costs[n] = new_cost # 就更新该邻居的开销
            parents[n] = node # 同时将该邻居的父节点设置为当前节点
    processed.append(node) # 将当前节点标记为处理过
    node = find_lowest_cost_node(costs) # 找出接下来要处理的节点,并循环

def find_lowest_cost_node(costs):
    lowest_cost = float("inf")
    lowest_cost_node = None
    for node in costs:  # 遍历所有节点
        cost = costs[node]
        if cost < lowest_cost and node not in processed: # 如果当前节点的开销更低且未处理过
            lowest_cost = cost # 就将其视为开销最低的节点
            lowest_cost_node = node
    return lowest_cost_node

贪婪算法

贪婪算法:每步都采取最优的做法。可理解为,每步都选择局部最优解,最终得到的就是全局最优解。
1- 背包问题
2- 集合覆盖问题

# 使用集合来表示要覆盖的州
states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"])
# 可供选择的广播台清单
stations = {}
stations["kone"] = set(["id", "nv", "ut"])
stations["ktwo"] = set(["wa", "id", "mt"])
stations["kthree"] = set(["or", "nv", "ca"])
stations["kfour"] = set(["nv", "ut"])
stations["kfive"] = set(["ca", "az"])
# 创建一个集合来存储最终选择的广播台
final_stations = set()
# 需要遍历所有的电视台,从中选择覆盖了最多的未覆盖州的广播台
while states_needed:
    best_station = None
    states_covered = set()
    for station, states in stations.items():
        # 计算交集& 并集| 差集-
        covered = states_needed & states
        if len(covered) > len(states_covered):
            best_station = station
            states_covered = covered

    states_needed -= states_covered
    final_stations.add(best_station)
print(final_stations)
# {'kfive', 'kthree', 'ktwo', 'kone'}

快速排序不是贪婪算法,广度优先搜索和狄克斯特拉算法是贪婪算法。
对于NP完全问题,还没有找到快速解决方案。
面临NP完全问题时,最佳的做法是使用近似算法。
贪婪算法易于实现、运行速度快,是不错的近似算法。

动态规划

动态规划先解决子问题,再逐步解决大问题。但仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用。动态规划可帮助在给定约束条件下找到最优解。
最长公共子串
并没有看懂
动态规划的实际应用
1- DNA链的相似性
2- git diff命令,指出两个文件的差异
3- 编辑距离(levenshtein distance)指出了两个字符串的相似程度
4- ……

K最近邻算法

回归或者分类

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值