剑指offer题目总结


剑指offer题目总结

链表题目

  • 从尾到头打印链表
  • 反转链表
  • 合并两个排序的链表(递归/遍历)
  • 两个链表的第一个公共节点(双指针/哈希表)
  • 链表中环的入口节点(快慢指针/字典)
  • 链表中倒数最后k个节点(快慢指针)
  • 复杂链表的复制(1. 复制 2. 随机指针复制 3.打断两个链表) -手写可能出错
  • 删除链表中的节点(简单遍历)

    总结:简单遍历+快慢指针+哈希

树题目

  • 二叉树的深度(简单递归/队列辅助层次遍历)
  • 按之字顺序打印二叉树(层次遍历 + flag判断奇偶层)
  • 二叉搜索树的第k个节点(深度优先遍历,结合二叉搜索树的特点)
  • 重建二叉树(递归 + 结合前序中序遍历的特点)
  • 树的子结构(递归,注意三种匹配情况)
  • 二叉树的镜像(递归,左右子树镜像,交换)
  • 从上往下打印二叉树(简单的层次遍历)
  • 二叉搜索树的后序遍历序列(递归,后序遍历,根节点)
  • 二叉树中和为某一值的路径1(递归,不需保存路径)
  • 二叉树中和为某一值的路径2(递归,保存路径, dfs)
  • 二叉搜索树与双向链表(中序遍历,维护一个pre_node)
  • 判断是不是平衡二叉树(递归判断,专门写一个判断树深度的函数即可)
  • 二叉树的下一个节点(获取中序遍历序列/分情况讨论)
  • 对称的二叉树(递归,输入两棵树,左右子树是否match, 因为单一递归,同时只能到一部分,需要两部分同步递归)
  • 把二叉树打印成多行(用队列实现树的BFS)
  • 序列化二叉树(确定规则,指针遍历,节点值后面加符号来分割树节点)
  • 二叉树中和为某一值的路径3(层次遍历 + dfs/借助哈希表,一次遍历)
  • 在二叉树中找到两个节点的最近公共祖先(dfs+最后一个共同节点/递归)
  • 二叉搜索树的最近公共祖先(简单递归,利用二叉搜索树的特点)

总结: 树的题目基本都是围绕递归遍历展开

  • 几种遍历方式: 前序、中序、后序、层次
  • 合理考虑递归边界,特殊情况

队列&栈

  • 用两个栈实现队列(进行两次压栈操作即可)
  • 包含min函数的栈(普通栈+最小栈)
  • 栈的压入弹出序列(辅助栈模拟)
  • 翻转单词序列(两次翻转/直接split+join)
  • 滑动窗口的最大值(双向队列,维护前向最大值)

总结:数据结构特点的基础应用

搜索算法

  • 数字在升序数组中出现的次数(二分查找 target-0.5 target+0.5)
  • 二维数组中的查找(有序数组,从角落开始搜索)
  • 旋转数组中的最小数字(二分查找,特殊情况考虑,注意等号)
  • 字符串的排列(遍历)
  • 数字序列中的某一位数字(模拟, 几位数字位数关系)

总结:二分搜索 or 模拟遍历

动态规划

  • 连续子数组的最大和(一维dp, 可以不另外开辟数组)
  • 连续子数组最大和(二)(一维dp,维护起始位置,可以不另外开辟数组)
  • 跳台阶(斐波那契数列)
  • 斐波那契数列
  • 正则表达式匹配(二维dp)
  • 跳台阶扩展问题($2^{n-1}$)
  • 矩阵覆盖(斐波那契数列)
  • 买股票的最好时机(一维dp)
  • 礼物的最大价值(二维dp, 可以不另外开辟数组)
  • 最长不含重复字符的子字符串(借助字典,1维dp)
  • 把数字翻译成字符串(一维dp)

总结: 这类问题的关键在于

  • 状态的定义
  • 状态转移方程的形式

回溯

  • 矩阵中的路径(dfs + 标志矩阵)
  • 机器人的运动范围(dfs + 标志矩阵)

dfs + 标志矩阵

排序

  • 数组中重复的数字(哈希/位置重排)
  • 数组中的逆序对(归并排序)
  • 最小的k个数
  • 数据流中的中位数

总结:熟练掌握归并排序和快速排序

位运算

  • 不用加减乘除做加法(异或运算获取非进位和,与运算加左移算子获取进位信息)
  • 二进制中1的个数(n&n-1, 将低位1变为0,注意处理负数)
  • 数值的整数次方(借助二进制运算实现快速幂)
  • 数组中只出现一次的两个数字(异或运算的特点)
  • 求1+2+…+n(通过与运算终止递归)

模拟

  • 顺时针打印矩阵(简单模拟,通过边界控制循环结束)
  • 扑克牌顺子(借助hash)
  • 把字符串转换成整数(去空格,找符号,转换,取模)
  • 表示数值的字符串

其他算法

  • 构建乘积数组
  • 第一个只出现一次的字符
  • 替换空格
  • 调整数组顺序使奇数位于偶数前面
  • 数组中出现超过一半次数的数字
  • 整数中1出现的次数
  • 把数组排成最小的数
  • 丑数
  • 和为S的连续正数序列
  • 和为S的两个数字
  • 左旋转字符串
  • 孩子们的游戏(约瑟夫环)
  • 字符流中第一个不重复地字符
  • 剪绳子
  • 调整数组顺序使奇数位于偶数前面
  • 剪绳子(进阶版)
  • 打印从1到最大的n位数

    python中常用数据结构模块

  1. 队列 queue.Queue()
  • Queue().qsize(): 返回队列的大小
  • Queue().empty(): 如果队列为空返回True,反之返回False
  • Queue().full(): 如果队列满了,返回True,反之返回False
  • Queue().get(): 获取队列的第一个值,出队列
  • Queue().put(): 写入队列
  • 题目: 从上往下打印二叉树
    import queue 
    class Solution:
      def PrintFromTopToBottom(self , root: TreeNode) -> List[int]:
          # write code here 
          res = [] 
          if not root:
              return res 
          q = queue.Queue() 
          q.put(root) 
          while not q.empty(): 
              cur_node = q.get() 
              res.append(cur_node.val) 
              if cur_node.left: 
                  q.put(cur_node.left) 
              if cur_node.right: 
                  q.put(cur_node.right) 
          return res
    
  1. 双向队列collections.deque()
  • deque(): 创建
  • deque().append(): 向队列中添加元素
  • deque().pop(): 抛出最后一个元素
  • deque().leftpop(): 抛出第一个元素
  • deque().extend(): 添加list项到原deque()
  • deque().extendleft(): 添加list项到原deque()头部
  • 题目: 滑动窗口的最大值

    from collections import deque 
    class Solution:
      def maxInWindows(self , num: List[int], size: int) -> List[int]:
          # write code here 
          res = [] 
          dq = deque()
          if size > len(num) or not size: 
              return [] 
    
          for i in range(size): 
              while len(dq) > 0 and num[dq[-1]] < num[i]: 
                  dq.pop() 
              dq.append(i) 
    
          for i in range(size, len(num)): 
              res.append(num[dq[0]]) 
              while len(dq) > 0 and dq[0] < i - size + 1: 
                  dq.popleft() 
              while len(dq) > 0 and num[dq[-1]] < num[i]:
                  dq.pop() 
              dq.append(i) 
          res.append(num[dq[0]]) 
          return res
    
  1. 小根堆heapq
  • heapq.heappush(pq, value) 入堆
  • heapq.heapreplace(pq,value) 替换堆中元素
  • heapq.pop(pq) 出堆
  1. collections.defaultdict()
    dict的一个子类,可以使创建的字典具有默认值,可以预先指定默认值类型:
    import collections 
    mp = collections.defaultdict(list) # 默认值为[]
    mp = collections.defaultdict(int)  # 默认值为0
    mp = collections.defaultdict(lambda:999) # 默认值为999
    
    在python中,可哈希的数据类型有:
  • 数字类型(intfloatbool), 字符串str、元组tuple

不可哈希的数据类型有:

  • 字典dict、列表list、集合set

    算法题常用解题思路

    递归
  • 什么样的问题可以用递归解决?
    • 主问题可以拆分为若干子问题
    • 主问题和子问题的解题思路一致
    • 存在终止条件
  • 递归问题如何解决?
    • 找到递推公式
    • 找到终止条件
    • 翻译成代码

文章作者: 思考猫
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 思考猫 !
评论
 上一篇
数据结构与算法 数据结构与算法
数据结构与算法算是必考内容,如果能在笔试/面试的过程中快速找到算法题的解题思路,无疑会给面试官留下很好的印象,这类题目主要考察两个方面: 数据结构的掌握程度,能否熟练掌握各类数据结构的特点及操作 常见算法,比如贪心算法、动态规划、BFS
下一篇 
赛尔号插件下载地址 赛尔号插件下载地址
不是每个人都应该像我这样去建造一座水晶大教堂,但是每个人都应该拥有自己的梦想,设计自己的梦想,追求自己的梦想,实现自己的梦想。梦想是生命的灵魂,是心灵的灯塔,是引导人走向成功的信仰。有了崇高的梦想,只要矢志不渝地追求,梦想就会成为现实,奋斗
2022-09-08
  目录