guojh's Blog.

数据结构算法面试题

字数统计: 5.4k阅读时长: 21 min
2020/04/04

数据结构算法高频题

在面试中,由于时间的限制,一般不会出太难的题,这和笔试是不同的。因此必须有针对性地学习和总结,比如分专题学习总结。把常见基础题掌握好,再去追求一些很trick的题。一题多解时,还要注意分析算法复杂度。另外,STL容器、算法等API要多熟悉。

数组

多总结

滑动窗口法

substring、subarray问题常用双指针滑动窗口法或DP。滑动部分的时间复杂度为O(n)。


字符串

多数问题与数组类似

栈

对称性与顺序性。如括号匹配等问题。

队列

哈希

链表

画图结合、快慢指针等技巧

树

首先考虑递归。求树的深度、树是否对称、是否平衡、是否BST、树的翻转(镜像),排序数组转BST等

follow up考虑迭代。

图

思路与“树”类似。图的几种表示、图的DFS、BFS遍历等。

排序

排序的实现、复杂度分析、链表排序

912. Sort an Array 数组排序

  • 插入排序类
    • 直接插入排序。从左往右排序,从右往左swap(插入到正确位置)。类似扑克牌理牌。适用于基本有序数据。
    • 希尔排序。略。
  • 选择排序类
    • 简单选择排序。每次选择最小的元素,并交换(每次只交换了一次)
    • 堆排序
      • 时间复杂度O(nlogn),空间复杂度O(1)。不稳定。
      • 属于选择排序。每次取堆顶元素
  • 交换排序类
    • 冒泡排序。交换相邻元素。适用于基本有序数据。
    • 快速排序
      • 时间复杂度最优O(nlogn),最差O(n^2);空间复杂度(调用栈空间)最优O(logn),最差O(n)。不稳定。
      • 关键代码:compare and swap
      • 参考:视频讲解1,视频讲解2,参考讲解
    • 快速排序优化
      • pivot的选择,每次越接近中值越好。策略:选择最后一个元素、随机选择、三数取中
      • 如果在比较时考虑进index,则任何不稳定算法可以变稳定
  • 归并排序类
    • 时间复杂度O(nlogn),空间复杂度O(n)。稳定。
    • 关键代码:merge two sorted array
    • 适用于:大数据量排序、外排序、链表排序、统计逆序对等

搜索

二分

堆

topK,第K大等类似问题

BuildHeap时间复杂度O(n),Heapify时间复杂度O(logn)。follow up:如何实现这两个函数。

回溯

回溯是进行暴力搜索,当中途发现已不满足求解条件时,则“回溯”返回,并尝试其他路径。用于Generate all xxx、Compute all xxx等问题,如八皇后、数独等。一般具有三要素:

choice:递归得到,normal case。

constraint:条件约束,if statement

goal:终止情况,base case


DP

DP问题有时可以先思考暴力递归的情况(top down方式),再思考如何记忆存储一些重复计算的子问题的解(top down+memoization),进一步地思考如何据此得到的DP方法(bottom up方式)。

易混概念:子序列subsequency可以不连续,而子串substring、子数组subarray必须连续

线性DP

子串子序列DP

注意DP的初始状态

递推型DP

找到线性递推公式,归纳法。通常只用O(n)时间复杂度,O(1)空间复杂度。

背包DP

0/1背包

  • 0/1背包问题 0-1 Knapsack Problem
    • 每一次的选择:0和1。在总weight有限的约束下,每一步都去最大化这两个Value
      • 要:V[i-1][w-wi]+Vi,前提要的起(w>=wi)
      • 不要:V[i-1][w]
    • 时间复杂度O(mn),空间复杂度O(mn)。因为每次只用到了上一行的结果,因此空间复杂度可以优化为O(n),即每次只保存上一行结果。
  • 416. Partition Equal Subset Sum 分割等和子集
    • 0/1背包问题,要求恰好取到背包容量。状态用bool表示,每次对两个状态取或
      • 要:V[i-1][w-wi],前提要的起(w>=wi)
      • 不要:V[i-1][w]
  • 494. Target Sum 目标和
    • 0/1背包问题,求方案数。
    • 两个状态+或-,而不是要或不要。因此需要注意列的范围是-sum到sum。每次对两个状态的方案数求和。
    • 参考讲解

完全背包

  • 139. Word Break 单词拆分
    • 类似完全背包,用bool表示每一个字母是否reachable
  • 140. Word Break II 单词拆分II
    • 首先利用Word Break I检查单词是否可拆分,然后再进行下一步(防止超时)
    • 基本思路和Word Break I一样:利用容器,存储单词拆分的中间结果
  • 279. Perfect Squares 完全平方数
    • 背包的总重是n;各物体的重量是1,4,9,...,x2,其中x2<=n
  • 322. Coin Change 零钱兑换
    • 完全背包(Unbounded Knapsack Problem):物体可以无限重复利用。使用1维数组存储即可
    • dp[i] = min(dp[i], dp[i-coin[j]] +1),j从0到n-1,i-coin[j]>=0
    • 完全背包问题中,一般会用两个循环。改变内外循环的先后顺序,运行的速度和效率可能不同。
  • 343. Integer Break 剪绳子
    • dp[i] = max(dp[i], dp[i]*dp[i-j]),j从1到i/2
    • follow up:贪心算法

矩阵路径类DP

记忆化 memoization

模拟

  • 134. Gas Station 加油站
    • 总gas>=总cost时,一定存在解
    • 第一个tank大于等于0的地方就是开始的位置
  • 扑克牌顺子
    • 排序,然后三步:统计0,统计gap(如遇到对子,则false),统计0是否足够弥补gap

数学与位运算

CATALOG
  1. 1. 数据结构算法高频题
    1. 1.1. 数组
      1. 1.1.1. 滑动窗口法
    2. 1.2. 字符串
    3. 1.3. 栈
    4. 1.4. 队列
    5. 1.5. 哈希
    6. 1.6. 链表
    7. 1.7. 树
    8. 1.8. 图
    9. 1.9. 排序
    10. 1.10. 搜索
    11. 1.11. 堆
    12. 1.12. 回溯
    13. 1.13. DP
      1. 1.13.1. 线性DP
      2. 1.13.2. 子串子序列DP
      3. 1.13.3. 递推型DP
      4. 1.13.4. 背包DP
      5. 1.13.5. 矩阵路径类DP
    14. 1.14. 模拟
    15. 1.15. 数学与位运算