算法题速查手册

Boyer-Moore 投票算法

初始化m*n二维数组:dp = [[1]*n for _ in range(m)]

每个key的value都是list的dict:tree = collections.defaultdict(list)

dict 计数:mydict[x] = mydict.get(x, 0) + 1

dict 排序: mylist = sorted(mydict.items(), key = lambda kv:(kv[1], kv[0]))

ASCII值:ord("A")

避免浮点数运算: math.floor( (x + (n-1)) / n ) = math.ceil( x / n ) = (x + (n-1)) // n

位运算

位运算符:

&  且
|  或
~  非
^  异或
<<  左移
>>  右移

Brian Kernighan 算法:令 x = x & (x-1),该运算将 x 的二进制表示的最后一个 1 变成 0.

排序

# 库函数
people.sort(key=lambda x: (-x[0], x[1])) # 按x[0]降序,x[1]升序

归并排序:

def MergeSort(nums):
    if len(nums) <= 1:
        return nums
    mid = len(nums) // 2 
    left = MergeSort(nums[:mid])
    right = MergeSort(nums[mid:])
    return Merge(left, right)
def Merge(left, right):
    r, l=0, 0
    result=[]
    while l<len(left) and r<len(right):
        if left[l] <= right[r]:
            result. Append(left[l])
            l += 1
        else:
            result. Append(right[r])
            r += 1
    result += list(left[l:])
    result += list(right[r:])
    return result
print MergeSort([1, 2, 3, 4, 5, 6, 7, 90, 21, 23, 45])

堆排序:https://aijishu.com/a/1060000000090217

import heapq

def HeapSort(nums):
  heap, res = [], []
  for num in nums:
    heapq.heappush(heap, num)
  while heap:
    res.append(heapq.heappop(heap))
  return res

def HeapSort(nums):
  heap, res = nums, []
  heapq.heapify(heap)
  while heap:
    res.append(heapq.heappop(heap))
  return res

print(HeapSort([6,8,1,6,4,9]))
# 'heap' is a heap at all indices >= startpos, except possibly for pos.  pos
# is the index of a leaf with a possibly out-of-order value.  Restore the
# heap invariant.
def _siftdown(heap, startpos, pos):
    newitem = heap[pos]
    # Follow the path to the root, moving parents down until finding a place
    # newitem fits.
    while pos > startpos:
        parentpos = (pos - 1) >> 1
        parent = heap[parentpos]
        if newitem < parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem

def _siftup(heap, pos):
    endpos = len(heap)
    startpos = pos
    newitem = heap[pos]
    # Bubble up the smaller child until hitting a leaf.
    childpos = 2*pos + 1    # leftmost child position
    while childpos < endpos:
        # Set childpos to index of smaller child.
        rightpos = childpos + 1
        if rightpos < endpos and not heap[childpos] < heap[rightpos]:
            childpos = rightpos
        # Move the smaller child up.
        heap[pos] = heap[childpos]
        pos = childpos
        childpos = 2*pos + 1
    # The leaf at pos is empty now.  Put newitem there, and bubble it up
    # to its final resting place (by sifting its parents down).
    heap[pos] = newitem
    _siftdown(heap, startpos, pos)

def heapify(x):
    """Transform list into a heap, in-place, in O(len(x)) time."""
    n = len(x)
    # Transform bottom-up.  The largest index there's any point to looking at
    # is the largest with a child index in-range, so must have 2*i + 1 < n,
    # or i < (n-1)/2.  If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
    # j-1 is the largest, which is n//2 - 1.  If n is odd = 2*j+1, this is
    # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
    for i in reversed(range(n//2)):
        _siftup(x, i)

def heappush(heap, item):
    """Push item onto heap, maintaining the heap invariant."""
    heap.append(item)
    _siftdown(heap, 0, len(heap)-1)

def heappop(heap):
    """Pop the smallest item off the heap, maintaining the heap invariant."""
    lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
    if heap:
        returnitem = heap[0]
        heap[0] = lastelt
        _siftup(heap, 0)
        return returnitem
    return lastelt
class Solution(object):
    def heap_sort(self, nums):
        n = len(nums)
        self.nums = nums

        # 初始化大顶堆
        for i in range(n//2-1, -1, -1): 
            self.build_heap(i, n-1)

        for i in range(n-1, -1, -1):
            nums[0], nums[i] = nums[i], nums[0] # 交换
            self.build_heap(0, i-1) # 调整大顶堆

        return nums

    def build_heap(self, i, n):
        nums = self.nums
        left, right = 2*i+1, 2*i+2 # 左右子节点的下标
        
        large_index = left
        if right <= n and nums[left] < nums[right]:
            large_index = right
        if nums[i] > nums[large_index]:
            large_index = i
 
        if large_index != i:
            nums[i], nums[large_index] = nums[large_index], nums[i]
            self.build_heap(large_index, n)

回溯

1. 求所有子集:https://leetcode.cn/problems/subsets/solution/hui-su-suan-fa-by-powcai-5/

时间复杂度 \(O(n×2^n)\),空间复杂度 \(O(n)\)

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
# 库函数
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        for i in range(len(nums)+1):
            for tmp in itertools.combinations(nums, i): # 长度为i的所有子集
                res.append(tmp)
        return res
# 迭代
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = [[]]
        for x in nums:
            res = res + [[x] + sub for sub in res]
        return res

[] 000

[1] 001 (往前面的加上001的1这一位)

[2] 010  (往前面的加上010的1这一位)
[2, 1] 011

[3] 100  (往前面的加上100的1这一位)
[3, 1] 101
[3, 2] 110
[3, 2, 1] 111
# 递归
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        res = []
        def helper(i, tmp):
            res.append(tmp)
            for j in range(i+1, n):
                helper(j, tmp+[nums[j]])
        helper(-1, [])
        return res

[] 000
[1] 001                                                                         [2] 010                            [3] 100 ([]最高位000,遍历001,010,100)
[1, 2] 011                             [1, 3] 101 ([1]最高位001,遍历010, 100)    [2, 3] 110  ([2]最高位010,遍历100)
[1, 2, 3] 111  ([1, 2]最高位010,遍历100)

2. 求全排列:https://leetcode.cn/problems/permutations/solution/hui-su-suan-fa-by-powcai-2/

时间复杂度 \(O(n*n!)\),空间复杂度 \(O(n)\).

# 库函数
def permute(self, nums: List[int]) -> List[List[int]]:
        return list(itertools.permutations(nums))
# 递归
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []
        def helper(candidates, tmp):
            if not candidates:
                res.append(tmp)
            for i in range(len(candidates)):
                helper(candidates[:i]+candidates[i+1:], tmp+[candidates[i]])
        helper(nums, [])
        return res
# 递归,两两交换
class Solution:
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def backtrack(first = 0):
            # 所有数都填完了
            if first == n:  
                res.append(nums[:])
            for i in range(first, n):
                # 动态维护数组
                nums[first], nums[i] = nums[i], nums[first]
                # 继续递归填下一个数
                backtrack(first + 1)
                # 撤销操作
                nums[first], nums[i] = nums[i], nums[first]
        
        n = len(nums)
        res = []
        backtrack()
        return res

链表

class Node:
    def __init__(self, val = None, next = None):
        self.val = val
        self.next = next

def create_link(link):
    root = Node(link[0])
    pre = root
    for i in range(1, len(link)):
        p = Node(link[i])
        pre.next = p
        pre = p
    return root

def print_link(root):
    p = root
    while p:
        print(p.val, end=",")
        p = p.next
    print()

link = [1, 3, 9, 2]
link_root = create_link(link)
print_link(link_root)
# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

二叉树

前序:中左右;
中序:左中右;
后序:左右中;
层次。

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self. Right = right

并查集

https://leetcode.cn/problems/evaluate-division/solution/pythonbing-cha-ji-fu-mo-ban-by-milomusia-kfsu/

class UnionFind:
    def __init__(self):
        """
        记录每个节点的父节点
        """
        self.father = {}
    
    def add(self, x):
        """
        添加新节点
        """
        if x not in self.father:
            self.father[x] = None

    def find(self, x):
        """
        查找根节点
        路径压缩
        """
        root = x

        while self.father[root] != None:
            root = self.father[root]

        # 路径压缩
        while x != root:
            original_father = self.father[x]
            self.father[x] = root
            x = original_father
         
        return root
    
    def merge(self, x, y):
        """
        合并两个节点
        """
        root_x,root_y = self.find(x),self.find(y)
        
        if root_x != root_y:
            self.father[root_x] = root_y

    def is_connected(self,x,y):
        """
        判断两节点是否相连
        """
        return self.find(x) == self. Find(y)

牛顿-拉弗森法求根号2

求多项式 f(x) = x^2-n = x^2-2 = 0 的根 k
k_better = k - f(k) / f'(k) = k - (k^2-2) / (2*k)

def newton_raphson(k, epsilon, n=2):
    while abs(k * k - n) >= epsilon:
        k = k - ((k * k - n) / (n * k))
    return k

print(newton_raphson(2, 0.00001))

https://blog.csdn.net/weixin_43031313/article/details/125469836

posted on 2022-04-24 23:36  HolaWorld  阅读(56)  评论(0编辑  收藏  举报

导航