leetcode链表反转总结——全部翻转,部分反转

leetcode链表反转(递归)总结——全部翻转,部分反转

参考:步步拆解:如何递归地反转链表的一部分

  • 由于链表反转使用迭代的思路进行实现比较简单,只是写法上比较复杂,所以这里仅整理记录一下递归反转链表的解法

一.全部反转

1.1 题目

  • 使用递归反转链表,并返回链表

1.2 解法

    /**
     * 递归反转链表
     * @param head
     * @return
     */
    public static ListNode reverseList(ListNode head) {
        if(head.next == null){
            return head;
        }
        ListNode last = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last ;
    }

1.3 算法过程详解

  • 对于递归切记的就是看代码的时候不要进去,因为脑子里根本没法压多个栈,一旦进入递归了,那么就把整个思路复杂化了。
  • 我们只需要关注两个地方:
    1) 第一个就是整个方法的作用是什么(传入值,操作,返回值)。
    2) 第二个就是base case,当递归到最底层了,该怎么操作,返回什么
  • 在链表递归反转的操作中,往往最重要的是反向操作,也就是递归到最后一个节点或者倒数第二个节点了,该怎么反转链表

1)递归操作(这里就是进行递归的地方)

ListNode last = reverseList(head.next);

函数的传入值:后置链表(head后面的链表)
函数的作用:将后置链表进行反转
函数的返回值:返回反转之后的第一个节点(也就是反转之前的最后一个节点)

注意:在这里我们无需关注函数是如何反转的,我们只需要关注返回的是什么,里面已经干了什么

假设我们想反转这个链表:
在这里插入图片描述
那么执行完这一步之后,已经变成了这个样子:

  • 此时head指向1,last 指向6,后置链表已经全部反转
  • 之后我们就要开始将1也开始加入反转链表中

在这里插入图片描述
2)反转操作

  • 第一行代码是让2的next指向1
  • 第二行的代码是让1的next指向null
  • 此时就已经完成了整个链表的反转
	head.next.next = head;
    head.next = null;

完成上述操作后,该链表已经变成这样:已经完成了整个链表的反转

在这里插入图片描述
3)base case

  • 当递归到最后一个节点的时候,返回该节点即可
 if(head.next == null){
            return head;
        }

至此,已经完成了链表反转操作,实际上这个函数会一直递归到倒数第二个节点,中间的反转操作会在倒数第二个节点开始进行操作,直到递归到第一个节点,中间的每一个节点都会进行反向操作,这也就是我之前说的为什么反向操作是最核心的地方。

二. 反转前n个节点

2.1 解法

/**
 * 递归反转前n个节点
 * @return
 */
ListNode successor;
public ListNode reverseListN(ListNode head, int n) {
    if(n == 1){
        successor= head.next;
        return head;
    }

    ListNode last = reverseListN(head.next,n-1);
    head.next.next = head;
    head.next = successor;
    return last;

}

2.2 算法过程详解

  • 实际上反转前n个链表节点跟反转全部节点区别仅仅在于base case和最后连接整个链表的操作。
  • 这个n的意义仅仅是判断是否到达了最后一个要反转的链表节点,也就是base case的判断条件点
reverseListN(head.next,n)
  • 整个大方法的作用就是将前n个链表节点反转,并返回第n个节点指针

在这里插入图片描述

1)递归

ListNode last = reverseListN(head.next,n-1);
  • 方法返回last指向的就是第n个节点

2)操作

  • 反转操作,将该节点也加入反转
head.next.next = head;

在这里插入图片描述

3)base case

  if(n == 1){
        successor= head.next;
        return head;
    }
  • 这里的successor指向的是第n+1个节点,因为将前n个节点反转之后,还需要将后面的节点连起来,所以需要记录

4)连接链表

head.next = successor;

三. 反转部分链表

3.1 题目

在这里插入图片描述

3.2 思路

  • 如果上面的链表看懂了,其实反转部分链表就非常简单了,因为只需要定位到需要反转链表的第一个节点,再使用反转前n- m个节点的方法就可以完成操作
ListNode reverseBetween(ListNode head, int m, int n) {
    // base case
    if (m == 1) {
        return reverseN(head, n);
    }
    // 前进到反转的起点触发 base case
    head.next = reverseBetween(head.next, m - 1, n - 1);
    return head;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值