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)递归操作(这里就是进行递归的地方)

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;
}
经验分享 程序员 微信小程序 职场和发展