前端算法小白入门

121 阅读4分钟

第一章

大O表示与常量乘除等无关,与增速角度有关,比如看的是坐标上的增长趋势

二分查找py版本:

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

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

print(binary_search([1,2,5,6,8,10],5))

第二章

数组和链表

选择排序

def findSmalllest(list):
    smallest = list[0]
    smallest_index = 0
    for i in range(1, len(list)):
        if list[i] < smallest:
            smallest = list[i]
            smallest_index = i
    return smallest_index

def selectionSort(list):
    newArray = []
    for i in range(0, len(list)):
        smallest = findSmalllest(list)
        newArray.append(list.pop(smallest))
    return newArray

print(selectionSort([3,1,8,5]))

第三章-递归

递归与循环的去呗,递归更好理解,循环可能性能更好

递归需要有递归条件和基线条件

递归可能导致栈占用很多,解决方法是改循环或者尾递归

第四章-分而治之

分而治之又名d&c,不属于算法,属于一种解决问题的思路

1.找出简单的基线条件

2.确定如何缩小问题的规模,使其符合基线条件

def getSum(arr):
    if arr==[]:
        return 0
    return arr[0] + getSum(arr[1:])

print(getSum([1,3,5,7]))
def getBiggest(arr):
    if len(arr)==2:
        return arr[0] if arr[0] > arr[1] else arr[1]
    max = getBiggest(arr[1:])
    return arr[0] if arr[0] > max else max

print(getBiggest([1,3,11,5,7]))

快速排序

def quickSort(arr):
    if len(arr)<2:
        return arr
    else:
        pivot = arr[0]
        left = [i for i in arr[1:] if i <= pivot]
        right = [i for i in arr[1:] if i > pivot]
        return quickSort(left) + [pivot] + quickSort(right) 

print(quickSort([10,5,2,3]))

快速排序在最糟糕的情况是0n方,平均是onlog,而合并排序是olog,为什么说快速排序大多情况比合并快呢,因为我们平时算大o是忽略执行时间这个常量的,通常这个常量在快速排序中要比合并小很多且不太出现最糟糕的情况,所以很多场景下我们会用快速排序

第五章 hash表

hash的查找速度一般来说比二分的速度要快,一般的语言比如python都已经内置了hash(字典)

1.一个输入一个确定的输出index

2.需要一个hash函数

减少冲突提高性能的办法:保证装填因子合理(0.7)以及减少冲突提高函数性能

应用场景:1.映射 2.防止重复 3:缓存

voted = {}
def check_Vote(name):
    if voted.get(name):
        print('kick')
    else:
        voted[name] = True
        print('vote')

第六章 广度遍历

可以想象成一个图,从我开始找联系人,先找到我认识的作为第一层,再是我认识的认识的人作为第二层,这个查找顺序不能变,不然找到的就不是最短路径,所以建议用队列。

我对应的认识的人,可以用hash

广度可以解决 1.从起点到终点路径 2.从起点到终点最短路径(不算加权)

广度搜索的大o是o(e+v)

from collections import deque

graph={}
graph['you'] = ['alice','cathy','mengmeng']
graph['alice'] = ['tingjie','baoge']
graph['cathy'] = ['mya','cora','gary']

def persion_is_seller(name):
    if name == 'cathy':
        return True
    return False

def search(name):
    search_queue = deque()
    search_queue += graph[name]
    searched = []
    print(search_queue)
    while search_queue:
        person = search_queue.popleft()
        if person not in searched:
            if persion_is_seller(person):
                print('found',person)
                return True
            else:
                search_queue += graph[person]
                searched.append(person)
    return False

search('you')

第七章-迪科斯特拉算法(找最小带全路径)

这个算法只适用于有向无环图,且带全路径不能是负数

1.找到出发点到能到的点最小的

2.基于最小的再找最小的不断更新

3.最后找到一段最小的

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'] = {}


infinity = float('inf')
costs = {}
costs['a'] = 6
costs['b'] = 2
costs['fin'] = infinity

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
    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

node = find_lowest_cost_node(costs)
while node is not None:
    cost = costs[node]
    neighbors = graph[node]
    for n in neighbors:
        new_cost = cost + neighbors[n]
        if new_cost < costs[n]:
            costs[n] = new_cost
            parents[n] = node
    processed.append(node)
    node = find_lowest_cost_node(costs)

print(costs)
print(parents)

第八章 贪婪算法

选取当前最佳的一步,不断重复到最后,结果十分近似最优解

背包可以用贪婪也可以用动态规划

from collections import OrderedDict

states_needed = set(['mt','wa','or','id','nv','ut','ca','az'])

stations = {}
stations['knone'] = set(['id','nv','ut'])
stations['ktow'] = set(['wa','id','mt'])
stations['kthree'] = set(['or','nv','ca'])
stations['kfour'] = set(['nv','ut'])
stations['kfive'] = set(['ca','az'])

final_stations = []

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.append(best_station)

print('final',final_stations)

np完全问题:比如旅行商问题,集合问题都属于

对于np完全问题只找到近似方法解决,还没找到最佳解决方案

第九章:动态规划

贪婪算法是背包问题的近似解决

动态规划是背包问题的完美解决方案

动态规划只能解决子问题是离散的情况,子问题之间不能有牵连

最大公共子序列lcp用的也是动态规划(如果元素相同,左上角+1,如果不同取左边和上边值大的那个)

常见的word以及git diff也是用动态规划实现的

第十章(k最近邻即knn算法)

1.分类 2.找到与之最近的几个数 3.看归于哪个分类的更多

经典应用:推荐算法

如何找到相似性更高的,主要是找出特征值然后将其化为向量找出距离之间最短的

预测数字:回归(找到距离最近的k个求平均值)

很多语音识别,人脸识别,图像识别(如ocr)都是用的knn,1。训练 2.取到特征值找邻居

第十一章 常用算法介绍

排序二叉树常用于数据库

反向索引常用于搜索引擎如es

傅立叶函数常用于mp3,dna分析等

并行算法,如何让多核一起处理,mapreduce,映射+归并,分布式算法核心

布隆过滤器,概率型存储,可以用存储海量信息而占用的内存空间很小,如典型的hyperloglog

sha算法,常用语比较文件是否相同,检查密码是否正确

diffie-hellman算法,有替代rsa加密的趋势

线性规划,用有限的条件实现利润最大化