看完这篇精选面试算法题集合,你也能进大厂!(Python版)

根据数据结构,可以将算法题分成数组、字符串、链表、栈、队列、树等几大类。根据算法,可以将题分为递归和循环、查找和排序、回溯法、动态规划和贪婪算法、位运算、DFS&BFS、随机、数学等几大类。而算法和数据结构又是一个排列组合的过程。

上面介绍的算法和数据结构都是要十分熟练的掌握的,就不再总结,下面我们总结的是一些常见的技巧,有了这些技巧伴身,相信秋招算法题不在话下。

文章目录

    • 一、经典类型
      • 1.滑动窗口
      • 2.双指针
      • 3.快慢指针“龟兔赛跑”
      • 4.区间合并
      • 5.循环排序
      • 6.链表翻转
      • 7.树BFS
      • 8.树DFS
      • 9.双堆
      • 10.子集(多重DFS)
      • 11.改造二分
      • 12.TOPK
      • 13.多路归并
      • 14.0/1背包
      • 15.拓扑排序
    • 二、动态规划
      • 1.0/1背包(6)
      • 2.无限背包(5)
      • 3.斐波那契数列(6)
      • 4.回文系列(5)
      • 5.最长子字符串系列(13)

一、经典类型

1.滑动窗口

这种类型的题通常结合数组和链表这两种数据结构,窗口大小可能是固定的也可能是变化的。
题目关键词:

  • 链表、数组、字符串
  • 求最长/最短子字符串或者某些特定的长度要求

经典题目:滑动窗口四题小结

2.双指针

同向双指针和异向双指针。
通常用于解决排好序的数组或者链表中寻找对子。比如比较数组中每个元素和其他元素的关系。
【使用双指针为了将时间复杂度从O(n2)降低到O(n)】
识别关键词:

  • 排好序的数组和链表,在里面找一些组合满足某种限制条件
  • 组合是一对数,三个数或者一个子数组

3.快慢指针“龟兔赛跑”

通常用于解决有环的链表和数组。
识别关键词:
环形链表,环形数组
需要知道链表长度或者某个特别位置的信息
双指针和快慢指针区分:
单链表不能用双指针,判断链表是否回文需要用快慢指针来找到中间元素。

4.区间合并

处理有区间重叠的高效技术,一共分为六种情况。
识别关键词:

  • 产生一堆相互之间没有交集的区间
  • 重叠区间

5.循环排序

用来处理数组中数值限定在一定区间的问题。
方法:遍历数组中的元素,如果当前数不在它应该在的位置上,就交换与应该在的位置上的那个数。

识别关键词:

  • 排好序的数组,数值在某一定的区间
  • 排好序/翻转过的数组中,寻找丢失的/重复的/最小的元素

6.链表翻转

适用于翻转链表中的某一段节点,原地翻转。
方法:每次翻转一个节点,需要current、previous两个变量,previous总是指向刚处理完的节点。
识别关键词:

  • 翻转链表且不能使用额外空间

7.树BFS

适用于需要遍历一棵树且需要一层层的遍历的问题。
借助于队列把根节点加入到队列中,不断遍历,直到队列为空,每次循环把头结点拿出来做一些操作,删除的时候将其孩子节点加入到队列中。
识别关键词:

  • 层序遍历

8.树DFS

适用于深搜实现树的遍历。
方法:使用递归或者迭代栈的方式。从根节点开始,如果该结点不是叶子节点,需要区别我们是先处理根节点,处理孩子节点之间处理根节点,还是处理完所有孩子再处理根节点(分别对应于前中后序),然后递归处理当前节点的左右孩子。
识别关键词:

  • 按前中后序的DFS方式遍历树
  • 该问题的解一般离叶子节点比较近

9.双堆

适用于包含可以分为两队的数字。将数字分成两半,小的放在一起,大的放在另一半。
方法:
一个最小堆用来寻找最小元素,一个最大堆拿到最大元素。可以使用O(1)的时间找到两边的最大或最小元素。从两个堆顶找到数字,从而计算出中位数。
识别关键词:

  • 优先队列、计划安排
  • 找一组数中的最大/最小/中位数
  • 涉及到二叉树数据结构

10.子集(多重DFS)

适用于排列组合问题
方法:使用BFS来处理这些问题。
识别关键词:

  • 找数组的组合或者排列

11.改造二分

适用于输入是拍好序的数组、链表或者矩阵,要我们寻找某些特定元素。
方法:对于一组满足上升排列的数集来说,步骤如下:
识别关键词:

  • 排好序的

12.TOPK

适用于让我们求解最大/最小/最频繁的K个元素的题。
方法:堆。Java中叫优先队列,PriorityQueue。
识别关键词:

  • 求最大/最小/最频繁的前K个元素
  • 通过排序去找一个特定的数

13.多路归并

适用于涉及到多组排好序的数组的问题。
方法:输入是K个排好序的数组,将每个数组的最小元素加入到最小堆,从而得到全局最小值,再从该元素所在的数组里取出其后面紧挨着的元素,加入堆。直到处理完所有元素。
识别关键词:

  • 输入排序好的数组、链表或者矩阵
  • 合并多个排好序的集合,或者找到这些集合中最小的元素

14.0/1背包

见下面第二部分“动态规划”

15.拓扑排序

适用于寻找一种线性的顺序,元素之间具有依赖性。比如,事件B依赖于事件A,A在拓扑排序顺序中排在B的前面。

方法:1)初始化;2)创建图,计算每个节点的入度;3)找所有的起点;4)排序。
识别关键词:

  • 处理无环图
  • 以一种有序的秩序更新输入元素
  • 处理的输入遵循某种特定的顺序

二、动态规划

1.0/1背包(6)

Leetcode0-1背包小结(Python)

2.无限背包(5)

Leetcode完全/无限背包小结(Python)

3.斐波那契数列(6)

4.回文系列(5)

5.最长子字符串系列(13)

最长公共子序列

【题目地址】

#闫氏DP分析法,链接地址 https://www.acwing.com/video/946/
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        #状态表示:集合:考虑text1的前i个字符和text2的前j个字符,两者中的公共子串    属性:最大
        #状态计算:00 01 10 11 f(i-1, j-1) f(i-1, j) f(i, j-1) f(i-1, j-1)+1
        dp = [[0 for i in range(len(text2)+1)] for j in range(len(text1)+1)]
        for i in range(1, len(text1)+1):
            for j in range(1, len(text2)+1):
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
                if text1[i-1] == text2[j-1]:dp[i][j] = max(dp[i-1][j-1]+1, dp[i-1][j-1])
        return dp[-1][-1]

你可能感兴趣的:(朱滕威的面试之路)