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. 数学与位运算