• 面试-算法笔记


    import time 
    import random
    
    def cal_time(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("%s Running time: %s"%(func.__name__, (end_time - start_time)))
            return res
        return wrapper
    

    堆排序

    import random
    import time
    
    def sift(li, low, high):
        i = low 
        tmp = li[low]
        j = 2 * i + 1
        while j <= high:
            if j < high and li[j + 1] > li[j]:
                j += 1
            if li[j] > li[i]:
                li[i], li[j] = li[j], li[i]
                i = j
                j = 2 * i + 1
            else:
                break
    @cal_time  
    def tree_sort(li, low, high):
        n = len(li) - 1
        # 构造堆
        for i in range((n - 1) // 2, -1, -1):
            sift(li, i, n)
        # 挨个出数
        for j in range(n , -1, -1):
            li[0], li[j] = li[j], li[0]
            sift(li, 0, j - 1)
            
    if __name__ == "__main__":
        li = list(range(10000))
        random.shuffle(li)
        tree_sort(li, 0, len(li) - 1)
        print(li)
        
    

    快速排序

    def partition(li, low, high):
        tmp = li[low]
        while low < high:
            while low < high and li[high] > tmp:
                high -= 1
            li[low] = li[high]
            while low < high and li[low] < tmp:
                low += 1
            li[high] = li[low]
        else:
            li[low] = tmp
        return low
    
    def quick_sort(li, low, high):
        if low < high:
            mid = partition(li, low, high)
            quick_sort(li, low, mid - 1)
            quick_sort(li, mid + 1, high)
            
    @cal_time   
    def majia(*args, **kwargs):
        quick_sort(*args, **kwargs)
    
    li = list(range(10000))
    random.shuffle(li)
    majia(li, 0, len(li) - 1)
    print(li)
                
        
    

    冒泡排序

    @cal_time
    def bubble_sort(li):
        n = len(li) - 1
        for i in range(n, -1, -1):
            for j in range(i):
                if li[j] > li[j + 1]:
                    li[j], li[j + 1] = li[j + 1], li[j]
                    
    # 冒泡 排序优化: 
    def optimize_bubble_sort(li):
        for i in range(len(li)-1):
            exchange = False
            for j in range(len(li)-i-1):
                li[j],li[j+1] = li[j+1],li[j]
                exchange = True
            if not exchange:
                break
    #  最好: O(n)  中等 和 最坏 为 O(n^2)
    
    li = list(range(1000))
    random.shuffle(li)
    bubble_sort(li)
    print(li)
    

    选择排序

    #  选择排序: 学算法的 时候尽量 不要用 内置函数  
    # 不稳定 , 飞着 换的
    @cal_time
    def select_sort(li):
        for i in range(len(li)):
            min_pos = i
            for j in range(i+1,len(li)):
                if li[min_pos] > li[j]:
                    min_pos = j
            li[min_pos],li[i] = li[i],li[min_pos]
                
    li = list(range(1000))
    random.shuffle(li)  # 打乱
    select_sort(li)
    print(li)
    

    插入排序

    @cal_time
    def tea_insert_sort(li):
        for i in range(1,len(li)):
            tmp = li[i]
            j = i - 1
            while j >= 0 and li[j] > tmp:
                li[j+1] = li[j]
                j -= 1
            li[j+1] = tmp
            
    # 插入排序  优化 
    @cal_time
    def insert_sort02(li):   #  O(n^2)
        for s in range(1,len(li)):
            tmp = li[s]
            for n in range(s-1,-2,-1):
                if li[n] < tmp:
                    break
                li[n+1] = li[n]
            li[n+1] = tmp
            
    li= list(range(10000))
    random.shuffle(li)
    tea_insert_sort(li)
    
    

    迷宫问题

    
    suosuo = [
        [1,1,1,1,1,1,1,1,1,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,0,0,1,1,0,0,1],
        [1,0,1,1,1,0,0,0,0,1],
        [1,0,0,0,1,0,0,0,0,1],
        [1,0,1,0,0,0,1,0,0,1],
        [1,0,1,1,1,0,1,1,0,1],
        [1,1,0,0,0,0,0,0,0,1],
        [1,1,1,1,1,1,1,1,1,1]
    ]
    
    dirs = [
        lambda x, y: (x - 1, y),
        lambda x, y: (x, y + 1),
        lambda x, y: (x + 1, y),
        lambda x, y: (x, y - 1),
    ]
    
    # 深度优先
    def migong_deep(x1, y1, x2, y2):
        stack = []
        stack.append((x1, y1))
        suosuo[x1][y1] = 2
        while len(stack) > 0:
            cur_node = stack[-1]
            if cur_node == (x2, y2):
                print("到达终点,")
                for i,v in enumerate(stack):
                    print(i, v)
                return True
            for d in dirs:
                next_node = d(*cur_node)
                if suosuo[next_node[0]][next_node[1]] == 0:
                    stack.append(next_node)
                    suosuo[next_node[0]][next_node[1]] = 2
                    break
            else:
                stack.pop()
        else:
            print("There is no way")
            return False
    
    # 广度优先
    from collections import deque
    
    def migong_wide(x1, y1, x2, y2):
        q= deque()
        q.append((x1, y1, -1))
        suosuo[x1][y1] = 2
        traceback = []
        while len(q) > 0:
            cur_node = q.popleft()
            traceback.append(cur_node)
            if cur_node[:-1] == (x2, y2):
                path = []
                i = len(traceback) - 1
                while i >= 0:
                    path.append(traceback[i][:-1])
                    i = traceback[i][2]
                path.reverse()
                for i,v in enumerate(path):
                    print(i, v)
                return True
            for d in dirs:
                next_x, next_y = d(cur_node[0], cur_node[1])
                if suosuo[next_x][next_y] == 0:
                    q.append((next_x, next_y, len(traceback) - 1))
                    suosuo[next_x][next_y] = 2
        else:
            print("There is no way")
            return False
        
    migong_wide(1, 1, 8, 8)            
    # migong_deep(1, 1, 8, 8)            
    

    基数排序

    # 基数 排序
    @cal_time
    def radix_sort(li):     # O(nk) k 表示位数 ,  和 最大数 的 位数 有关系 , 只能 处理整数 
        max_num = max(li)
        i = 0 
        while (10 ** i < max_num):
            buckets = [[] for _ in range(10)]
            for val in li:
                digit = val // (10 ** i) % 10
                buckets[digit].append(val)
            li.clear()
            for bucket in buckets:
                for val in bucket:
                    li.append(val)
            i += 1
    
    li = list(range(1000))
    random.shuffle(li)
    radix_sort(li)
    print(li)
    

    归并排序

    def merge(li,low,mid,high):
        # mid  为 分割线 左边 元素的 下标 
        # 列表 两段有序 [low,mid] ,[mid+1,high]
        i= low
        j = mid + 1
        li_tmp = []  # 升序
        while i <= mid and j <= high:
            if li[i] < li[j]:
                li_tmp.append(li[i])
                i += 1
            else:
                li_tmp.append(li[j])
                j += 1
        while i <= mid:
            li_tmp.append(li[i])
            i +=1
        while j <= high:
            li_tmp.append(li[j])
            j += 1
        # 把 排序后的列表 写入到 原先列表的  [low,high] 的区间中 去
    #     for i in range(low,high+1):
    #         li[i] = li_tmp[i-low]
        li[low:high+1] = li_tmp
    
    def merge_sort(li,low,high):
        if low < high:
            mid = (low + high) // 2
            merge_sort(li,low,mid)
            merge_sort(li,mid+1,high)
            merge(li,low,mid,high)
      
    #  套个 马甲
    @cal_time
    def majia(li,low,high):
        merge_sort(li,low,high)
        
    
    li = list(range(100))
    random.shuffle(li)
    majia(li,0,len(li)-1)
    print(li)
    

    斐波那契数列

    def feibo(n):  #  
        if n == 0 or n == 1:
            return 1
        return feibonaqi(n-1) + feibonaqi(n-2)
    
    # 避免重复计算
    @cal_time
    def feibo01(n):   # S(n) = O(n) = T(n)  
        li = [1,1]
        for s in range(2, n+1):
            li.append(li[-1] + li[-2])
        return li[n]
    # 节省空间
    @cal
    def feibo02(n):
        a = 1
        b = 1
        for s in range(2,n+1):
            c =- a + b
            a = b
            b = c
        return c
    

    汉诺塔问题

    # 汉诺塔 问题
    def hanoi(n,A,B,C):
        if n>0:
            hanoi(n-1,A,C,B)
            print('%s--->%s'%(A,C))
            hanoi(n-1,B,A,C)
    hanoi(4,'A','B','C')
    

    计数排序

    @cal_time
    def count_sort(li,max_num=100):
        count = [0 for _ in range(max_num+1)]
        for val in li:
            count[val] += 1
        li.clear()
        for i,v in enumerate(count):
            for s in range(v):
                li.append(i)
    
    li = [random.randint(0,100) for _ in range(10000)]
    random.shuffle(li)
    count_sort(li)
    print(li)
    

    希尔排序

    def insert_sort(li,d):   #  O(n^2)
        for s in range(d,len(li)):
            tmp = li[s]
            for n in range(s-d,-2,-d):
                if li[n] < tmp:
                    break
                li[n+d] = li[n]
            li[n+d] = tmp
    
            
    # 希尔排序
    @cal_time
    def shell_sort(li):
        d = len(li) // 2
        while d  > 0:
            insert_sort(li,d)
            d = d // 2
    
      
    li= list(range(100))
    shell_sort(li)
    print(li)
    

    二分查找

    # 二分法查找   (候选区 )
    def bin_search(collect,value):  # O(logn)
        low = 0
        high = len(collect)-1
        while high >= low:
            mid = (low + high) // 2
            if collect[mid] == value:
                return mid
            if value > collect[mid]:
                low = mid + 1
            else:
                high = mid -1
        return -1
    
    li = list(range(1,4500545,3))
    print(bin_search(li,22))
    
    # 递归  式的 二分查找
    # 但: 尾递归 ,会变为循环,一样的 效率 ,对 python 而言 没有优化 ,还是慢 
    def bin_recursive(li,val,low,high):  
        if low <= high:
            mid = (low + high) // 2
            if val == li[mid]:
                return mid
            elif val < li[mid]:
                return bin_recursive(li,val,low,mid-1)
            else:
                return bin_recursive(li,val,mid+1,high)
        else:
            return -1
    li = list(range(1,4500545,3))
    print(bin_recursive(li,22,0,1000))
    

    单链表

    class Node:
        def __init__(self,data=None):
            self.data = data
            self.next = None
    
    # head ---> a ----> b----> c -----> d
    
    head = Node()  #  data 可以 来存储 链表的长度
    
    a = Node(1)
    b = Node(2)
    c = Node(3)
    d = Node(4)
    
    head.next = a  # 头结点 , 空链表 表示为 haad 节点 的 next 无 指向
    a.next = b
    b.next = c 
    c.next = d
    
    # while  遍历 链表
    # while 1:
    #     node = a.next
    #     if not node:
    #         break
    #     print(node.data)
    #     a = node
    
    # 迭代 遍历 输出 链表 每个元素
    def output(start_node):
        if not start_node:
            return
        print(start_node.data)
        output(start_node.next)
        
        
    class LinkList:
        def __init__(self,li,method='head'):
            self.head = None
            method ='create_linklist_'+ method.strip() 
            if hasattr(self,method):
                func = getattr(self,method)
                func(li)
            else:
                raise ValueError('method  argument is  Error......') 
                
            
        def create_linklist_head(self,li): # 头插法 将 一个 列表 转化 为链表
            self.head = Node(0)
            for v in li:
                n = Node(v)
                n.next = self.head.next
                self.head.next = n
                self.head.data += 1
        
        def create_linklist_tail(self,li):  # 尾 插法, 将一个列表转化 为链表
            self.head = Node(0)
            tail = self.head
            for i in li:
                v = Node(i)
                tail.next = v
                tail = v
                self.head.data += 1
        
        def shiwei(self,start):  # 迭代 遍历链表
            if not start :
                return 
            print(start.data)
            self.shiwei(start.next)
    
        def print_linklist(self):
            start = self.head
            self.shiwei(start)
     
    # 链表 的  删除
    # curNode.next = curNode.next.next
    #  文件系统 和 区块链 
    # 硬盘 的基本单位 为 block = 4 K
    
    from collections import deque
    shi = deque()
    
        
    
    
    li = range(20)
    shiwei = LinkList(li,method='head')
    shiwei.print_linklist()
    
    
    

    找错, 快速排序

    def _quick_sort_version2(li):  # 有误
        print("-------------", len(li))
        if not li:
            return []
        if len(li) == 1:
            return li
        if len(li) == 2:
            if li[0] > li[1]:
                li.reverse()
                return li
    #     if len(li) == 3:
            
        tmp = li[0]
        left = [v for v in li[1:] if v < tmp ]
        right = [v for v in li[1:] if v >= tmp]
        left = _quick_sort_version2(left)
        right = _quick_sort_version2(right)
        return left + [tmp,] + right
    @cal_time
    def quick_sort_version2(li):
        _quick_sort_version2(li)
                 
    li = list(range(100))
    random.shuffle(li)
    quick_sort_version2(li)
    print(li)
    
  • 相关阅读:
    爬取卡通图片
    python 列表生成式
    python 装饰器
    python 协程 and 进程
    ssh登录缓慢问题
    解决 input 元素点击有蓝色边框的问题
    JavaScript面试题总结系列(九)
    JavaScript面试题总结系列(八)
    JavaScript面试题总结系列(七)
    JavaScript面试题总结系列(六)
  • 原文地址:https://www.cnblogs.com/shiwei1930/p/11731677.html
Copyright © 2020-2023  润新知