前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • 前端算法面试

    • 快速上手——从0到1掌握算法面试需要的数据结构(一)
    • 快速上手——从0到1掌握算法面试需要的数据结构(二)
    • 快速上手——从0到1掌握算法面试需要的数据结构(三)
    • 递归初相见——二叉树递归遍历的三种姿势
    • 算法的衡量——轻松理解时间复杂度与空间复杂度
    • 数组的应用——真题归纳与解读
    • 字符串的应用——真题归纳与解读
    • 链表的应用——真题归纳与解读
      • 链表的合并
      • 链表结点的删除
      • 删除问题的延伸——dummy 结点登场
      • 小结
    • 快慢指针与多指针——玩转链表复杂操作
    • 姿势特别的链表——环形链表专题
    • 栈与队列怎么玩(上)
    • 栈与队列怎么玩(下)
    • 遍历专题 DFS 与 BFS
    • 场景化解读递归与回溯思想在真题中的应用
    • 二叉树真题归纳与解读
    • 特殊的二叉树——二叉搜索树专题
    • 特殊的二叉树——平衡二叉树专题
    • 特殊的二叉树——堆结构及其在排序中的应用
    • 排序算法专题(上)
    • 排序算法专题(下)
    • 普通人也能吃透的动态规划思想专题(上)
    • 普通人也能吃透的动态规划思想专题(下)
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

链表结构相对数组、字符串来说,稍微有那么一些些复杂,所以针对链表的真题戏份也相对比较多。 前面咱们说过,数组、字符串若想往难了出,那一定是要结合一些超越数据结构本身的东西——比如排序算法、二分思想、动态规划思想等等。因此,这部分对应的难题、综合题,我们需要等知识体系完全构建起来之后,在真题训练环节重新复盘。

但是链表可不一样了。如果说在命题时,数组和字符串的角色往往是“算法思想的载体”,那么链表本身就可以被认为是“命题的目的”。单在真题归纳解读环节,我们能讲的技巧、能做的题目已经有很多。结合实际面试中的命题规律,我把这些题目分为以下三类:

  • 链表的处理:合并、删除等(删除操作画个记号,重点中的重点!)
  • 链表的反转及其衍生题目
  • 链表成环问题及其衍生题目

本节我们就以链表的处理为切入点,一步一步走进链表的世界。

# 链表的合并

真题描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。

示例:

输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4
@前端进阶之旅: 代码已经复制到剪贴板

思路分析

做链表处理类问题,大家要把握住一个中心思想——处理链表的本质,是处理链表结点之间的指针关系。

这道题也不例外,我们先来看看处理前两个链表的情况:

  • 两个链表如果想要合并为一个链表,我们恰当地补齐双方之间结点 next 指针的指向关系,就能达到目的。
  • 如果这么说仍然让你觉得抽象,那么大家不妨把图上的6个结点想象成6个扣子:现在的情况是,6个扣子被分成了两拨,各自由一根线把它们穿起来。而我们的目的是让这六个扣子按照一定的顺序,串到一根线上去。这时候需要咱们做的就是一个穿针引线的活儿,现在线有了,咱缺的是一根针

这根针每次钻进扣子眼儿之前,要先比较一下它眼前的两个扣子,选择其中值较小的那个,优先把它串进去。一次串一个,直到所有的扣子都被串进一条线为止(下图中红色箭头表明穿针的过程与方向):

同时我们还要考虑 l1 和 l2 两个链表长度不等的情况:若其中一个链表已经完全被串进新链表里了,而另一个链表还有剩余结点,考虑到该链表本身就是有序的,我们可以直接把它整个拼到目标链表的尾部。

编码实现

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
const mergeTwoLists = function(l1, l2) {
  // 定义头结点,确保链表可以被访问到
  let head = new ListNode()
  // cur 这里就是咱们那根“针”
  let cur = head
  // “针”开始在 l1 和 l2 间穿梭了
  while(l1 && l2) {
      // 如果 l1 的结点值较小
      if(l1.val<=l2.val) {
          // 先串起 l1 的结点
          cur.next = l1
          // l1 指针向前一步
          l1 = l1.next
      } else {
          // l2 较小时,串起 l2 结点
          cur.next = l2
          // l2 向前一步
          l2 = l2.next
      }
      
      // “针”在串起一个结点后,也会往前一步
      cur = cur.next 

  }
  
  // 处理链表不等长的情况
  cur.next = l1!==null?l1:l2
  // 返回起始结点
  return head.next
};
@前端进阶之旅: 代码已经复制到剪贴板

# 链表结点的删除

我们先来看一道基础题目:

真题描述:给定一

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • 前端算法面试

    • 快速上手——从0到1掌握算法面试需要的数据结构(一)
    • 快速上手——从0到1掌握算法面试需要的数据结构(二)
    • 快速上手——从0到1掌握算法面试需要的数据结构(三)
    • 递归初相见——二叉树递归遍历的三种姿势
    • 算法的衡量——轻松理解时间复杂度与空间复杂度
    • 数组的应用——真题归纳与解读
    • 字符串的应用——真题归纳与解读
    • 链表的应用——真题归纳与解读
      • 链表的合并
      • 链表结点的删除
      • 删除问题的延伸——dummy 结点登场
      • 小结
    • 快慢指针与多指针——玩转链表复杂操作
    • 姿势特别的链表——环形链表专题
    • 栈与队列怎么玩(上)
    • 栈与队列怎么玩(下)
    • 遍历专题 DFS 与 BFS
    • 场景化解读递归与回溯思想在真题中的应用
    • 二叉树真题归纳与解读
    • 特殊的二叉树——二叉搜索树专题
    • 特殊的二叉树——平衡二叉树专题
    • 特殊的二叉树——堆结构及其在排序中的应用
    • 排序算法专题(上)
    • 排序算法专题(下)
    • 普通人也能吃透的动态规划思想专题(上)
    • 普通人也能吃透的动态规划思想专题(下)