刷题随记 - 1.反转链表系列

一、 反转整个链表

LeetCode 206 :https://leetcode-cn.com/problems/reverse-linked-list/

① 递归实现

参考:公众号labuladong

在这里插入图片描述
在这里插入图片描述
箭头所指,即坑所在,报错信息,因为 空 链表没有 next 指针,所以,head == null 这个判断条件必须要在 head.next == null 前面。

在这里插入图片描述
改为:

var reverseList = function(head) {
  if(head == null || head.next == null){
    return head
  }

  const last = reverseList(head.next)
  head.next.next = head
  head.next = null
  return last
};

在这里插入图片描述

思想非常之奇妙,相当于我执行了 reverseList 函数之后,我返回一个 原本 指向最结尾的指针,此时除了头节点以外,全都反过来了。

最后,处理一下头结点那部分的情况,返回 新的头指针(原先最后一位,现头指针) 即可。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结:

  • base case 语句很关键,要考虑好,不然会出现上面的报错情况
  • 不要跳进递归,正如公众号文章所说,你的脑袋能压几个栈?
  • 核心,相信函数定义,处理函数不能处理的情况即可
②迭代实现

先训练递归思想,迭代后面再说

二、反转部分链表

1. 反转前 n 个

在这里插入图片描述
与第一题的不同:

  • base case 不同,变成了 n == 1
  • head 不一定最后变成最后一个节点,所以要设置一个节点(称为后驱节点),它是第 n + 1 个节点,用来反转后,head.next = successor,将整个链表连接起来。
let successor = null

function reverseNList(head, n){
  if(n === 1){
    successor = head.next
    return head
  }
  let last = reverseNList(head.next, n - 1)
  head.next.next = head
  head.next = successor
  return last
}
2. 反转(m,n)个节点

LeetCode 92 https://leetcode-cn.com/problems/reverse-linked-list-ii/

思想,将问题由繁琐,转换成一般。
在这里插入图片描述
那反转链表的前 n 个 是非常简单的,我们如何做到呢?

对于 head 我们是从第 m 个元素开始反转,反转结束的位置是 n,那对于 head.next ,我们从第 m - 1 个元素开始反转,反转结束的位置是 n - 1。对于 head.next.next.....

迟早有一步,我们当前指针相当于第1个元素开始反转,反转 x 个元素。

所以,根据这个思想

let successor = null

function reverseNList(head, n){
    if(n === 1){
        successor = head.next
        return head
    }
    const last = reverseNList(head.next, n - 1)
    head.next.next = head
    head.next = successor
    return last
}

var reverseBetween = function(head, left, right) {
    if(left === 1){
        return reverseNList(head, right)
    }
    const last = reverseBetween(head.next, left - 1, right - 1)
    head.next = last
   return head
};

结束。

问题:

  • 为什么最后返回的是head?

不要陷入递归,这么想,我们将部分反转过来之后,返回的指针,是原先 第 n 个位置指针,此时 head 是 第 m - 1 个指针,这是需要将他们连接起来,因此 head.next = last,至于 第 m - 2 个指针,人家的 next 本来就指向第 m - 1 呀。

三、递归总结

所以,不要考虑这些七七八八的,你只需要想:

  1. 写一个 base case
  2. 调用函数完成工作
  3. 需要完成函数没有完成的工作(善后)
  4. 返回值

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值