2021-09-01-小白学习算法心得

本文摘自《算法图解》,今天学习了八个算法,如下所示:
1.数组和链表
- 数组的元素都在一起。
-  链表的元素是分开的,其中每个元素都存储了下一个元素的地址。
-  数组的读取速度很快。
-  链表的插入和删除速度很快

2.递归:我用我自己。有两个条件:基线条件和递归条件。
下面用python来举例:

def fact(x):
  if x == 1:
    return 1
  else:
    return x * fact(x-1)
print(fact(5))

3.快速排序
①分而治之:
②快速排序:

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,6,9,0]))

4.散列表
散列表形式:

book = {}
# an apple costs 67 cents
book["apple"] = 0.67
# milk costs $1.49
book["milk"] = 1.49
book["avocado"] = 1.49

散列表优势:
适合用于:
 模拟映射关系;
 防止重复;
 缓存/记住数据,以免服务器再通过处理来生成它们。

#如果你将已投票者的姓名存储在列表中,这个函数的速度终将变得非常慢,因为它
# 必须使用简单查找搜索整个列表。但这里将它们存储在了散列表中,而散列表让你能够迅速知道
# 来投票的人是否投过票。使用散列表来检查是否重复,速度非常快。
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")
print(voted)

运行结果图
6.广度优先搜索
注意:
①.队列和栈区别:队列是先入先出,栈是后进先出
②.图由节点和边组成,一个节点可能与众多节点直接相连,这些节点被称为邻居,实现图就是进行广度优先搜索的过程。

#解决问题:从自己的人脉圈中找到芒果供应商,先找自己的朋友,再找朋友的朋友,直到找到芒果供应商
from collections import deque
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 person_is_seller(name):#芒果供应商特征
 # return name[0] == 'p'
  if  name[0] == 'p':
      return True

def search(name):
    search_queue = deque()#创建一个队列
    search_queue += graph[name]#将name这个键对应的所有值信息加入到搜索队列中

    searched = []  # This array is how you keep track of which people you've searched before.
    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")

7.狄克斯特拉算法
原理:
①针对:有向箭头带权重,如图所示:
在这里插入图片描述
求从起点到终点开销最小值。
②算法实现过程:
本来想画个流程图,但能力有限表达不出来,这里有一个讲的很清晰的视频
【【史上最清晰】手写迪杰斯特拉-Dijkstra(考试用)-哔哩哔哩】https://b23.tv/JnanUy

代码实现如下:

# 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:#这个while循环在所有节点都被处理过后结束
    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:
            # 更新新的花费
            costs[n] = new_cost
            # 更新父节点
            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)

8.贪婪算法(理解不透彻,其实这个只是近似算法)
假设你办了个广播节目,要让全美50个州的听众都收听得到。为此,你需要决定在哪些广播台播出。在每个广播台播出都需要支付费用,因此你力图在尽可能少的广播台播出。
贪婪算法可化解危机!使用下面的贪婪算法可得到非常接近的解。
(1) 选出这样一个广播台,即它覆盖了最多的未覆盖州。即便这个广播台覆盖了一些已覆盖
的州,也没有关系。
(2) 重复第一步,直到覆盖了所有的州。
这是一种近似算法(approximation algorithm)。在获得精确解需要的时间太长时,可使用近
似算法。判断近似算法优劣的标准如下:
 速度有多快;
 得到的近似解与最优解的接近程度。
贪婪算法是不错的选择,它们不仅简单,而且通常运行速度很快。在这个例子中,贪婪算法
的运行时间为O(n2),其中n为广播台数量。

#输出:要求尽可能在少的广播台播出

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:#一直循环,知道states_needer为空
  best_station = None
  states_covered = set() #states_covered是一个集合,包含该广播台覆盖的所有未覆盖的州
  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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值