📜  面试题中的前 10 名算法 | 2套(1)

📅  最后修改于: 2023-12-03 15:42:26.909000             🧑  作者: Mango

面试题中的前 10 名算法

在程序员面试中,算法是一个非常重要的方面。有些算法是经典问题,每个应聘者都应该熟悉,而有些算法则是出现在某些公司的面试中常常被问到。以下是我们总结的面试题中的前 10 名算法。

1. 二分查找

二分查找是一种非常基本的算法。在一个有序数组中查找目标数字时,可以通过不断缩小查找范围来达到较快的查询时间复杂度。

def binary_search(lst, target):
    left, right = 0, len(lst) - 1
    while left <= right:
        mid = (left + right) // 2
        if lst[mid] == target:
            return mid
        elif lst[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1
2. 快速排序

快速排序是一种排序算法,通过不断将数据集分成较小的子集,再对这些子集进行排序,最终得到有序数据集的方法。

def quick_sort(lst):
    if len(lst) < 2:
        return lst
    pivot = lst[0]
    left = [x for x in lst[1:] if x < pivot]
    right = [x for x in lst[1:] if x >= pivot]
    return quick_sort(left) + [pivot] + quick_sort(right)
3. 滑动窗口

滑动窗口算法是解决一类子字符串或者子数组问题的方法。在一个字符串或者数组中,通过控制窗口的大小和移动来找到子字符串或者子数组的最优解。

def sliding_window(s, t):
    left, right = 0, 0
    need = Counter(t)
    window = {}
    valid = 0
    start = 0
    length = float('inf')
    while right < len(s):
        c = s[right]
        right += 1
        if c in need:
            window[c] = window.get(c, 0) + 1
            if window[c] == need[c]:
                valid += 1
        while valid == len(need):
            if right - left < length:
                start = left
                length = right - left
            d = s[left]
            left += 1
            if d in need:
                if window[d] == need[d]:
                    valid -= 1
                window[d] -= 1
    return s[start:start+length] if length != float('inf') else ''
4. 堆排序

堆排序是一种排序算法,通过建立一个最小(或最大)堆,不断弹出堆顶元素,得到排序后的数据集的方法。

def heap_sort(lst):
    def sift_down(start, end):
        root = start
        while True:
            child = 2 * root + 1
            if child > end:
                break
            if child + 1 <= end and lst[child] < lst[child + 1]:
                child += 1
            if lst[root] < lst[child]:
                lst[root], lst[child] = lst[child], lst[root]
                root = child
            else:
                break

    for start in range((len(lst)-2) // 2, -1, -1):
        sift_down(start, len(lst)-1)

    for end in range(len(lst)-1, 0, -1):
        lst[end], lst[0] = lst[0], lst[end]
        sift_down(0, end - 1)
    return lst
5. KMP 字符串匹配

KMP 算法是一种字符串匹配算法,在主串和模式串匹配时,不需要回溯主串的已经匹配的部分,大大提高了匹配的效率。

def kmp_search(s, p):
    def get_next(s):
        j, k = 0, -1
        next_lst = [-1] * len(s)
        while j < len(s) - 1:
            if k == -1 or s[k] == s[j]:
                j += 1
                k += 1
                next_lst[j] = k
            else:
                k = next_lst[k]
        return next_lst

    i, j = 0, 0
    next_lst = get_next(p)
    while i < len(s) and j < len(p):
        if j == -1 or s[i] == p[j]:
            i += 1
            j += 1
        else:
            j = next_lst[j]
    if j == len(p):
        return i - j
    else:
        return -1
6. 斐波那契数列

斐波那契数列是一种非常基础的数列,该数列的每一项都是前两项的和。

def fibonacci(n):
    if n in [0,1]:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
7. 最长公共前缀

求解最长公共前缀是字符串处理中的一个典型问题。可以通过比较每个字符串的每一位来解决这个问题。

def longest_common_prefix(strs):
    if not strs:
        return ''
    prefix = strs[0]
    for word in strs[1:]:
        while not word.startswith(prefix):
            prefix = prefix[:-1]
            if not prefix:
                return ''
    return prefix
8. 回文串

回文串是一个正着和反着读都一样的字符串,在字符串处理中比较常见。

def longest_palindrome(s):
    if not s:
        return ''
    def helper(s, l, r):
        while l >= 0 and r < len(s) and s[l] == s[r]:
            l -= 1
            r += 1
        return s[l+1:r]

    res = ''
    for i in range(len(s)):
        odd = helper(s, i, i)
        even = helper(s, i, i+1)
        if len(odd) > len(res):
            res = odd
        if len(even) > len(res):
            res = even
    return res
9. 并查集

并查集是一种数据结构,可以快速合并和查找不相交集合的信息。

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [1] * n
        self.count = n
    
    def find(self, i):
        if i != self.parent[i]:
            self.parent[i] = self.find(self.parent[i])
        return self.parent[i]
    
    def union(self, p, q):
        root_p = self.find(p)
        root_q = self.find(q)
        if root_p != root_q:
            if self.rank[root_p] > self.rank[root_q]:
                self.parent[root_q] = root_p
            elif self.rank[root_p] < self.rank[root_q]:
                self.parent[root_p] = root_q
            else:
                self.parent[root_q] = root_p
                self.rank[root_p] += 1
            self.count -= 1
10. 二叉树的遍历

二叉树的遍历是一个非常基础的数据结构问题。可以通过递归和迭代两种方式实现。

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def preorder_traversal(root):
    res = []
    def dfs(node):
        if not node:
            return
        res.append(node.val)
        dfs(node.left)
        dfs(node.right)
    dfs(root)
    return res

def inorder_traversal(root):
    res = []
    def dfs(node):
        if not node:
            return
        dfs(node.left)
        res.append(node.val)
        dfs(node.right)
    dfs(root)
    return res

def postorder_traversal(root):
    res = []
    def dfs(node):
        if not node:
            return
        dfs(node.left)
        dfs(node.right)
        res.append(node.val)
    dfs(root)
    return res

以上是我们总结的面试题中的前 10 名算法。这些算法都是非常基础的算法,特别是在数据结构和算法方面,实现这些算法的过程是非常丰富和有趣的。希望对你在面试中更好的发挥和掌握这些算法有所帮助。