20、反转单链表(labuladong)

递归魔法:反转单链表

1、递归反转整个链表

力扣第206题,反转链表

[206]反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    // 该函数的意思是,返回当前头节点为head,反转后的新的链表的头节点
    public ListNode reverseList(ListNode head) {
        // base case
        if (head == null || head.next == null) {
            return head;
        }
        // 拿到当前节点的下个节点的反转后的头节点
        ListNode last = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }
}

这个样子的递归我个人觉得很有意思,巧妙之处在于这两行代码:

head.next.next = head;
head.next = null;

可能有图更好理解:

在这里插入图片描述

  • 但是还是需要写一下利用指针进行反转单链表的代码
[206]反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    // 该函数的意思是,返回当前头节点为head,反转后的新的链表的头节点
    public ListNode reverseList(ListNode head) {
        // base case
        if (head == null || head.next == null) {
            return head;
        }
        ListNode pre = head, cur = head, next = head.next;
        head.next = null;
        while (next != null) {
            cur = next;
            next = next.next;
            cur.next = pre;
            pre = cur;
        }
        return cur;
    }
}

2、反转链表前N个节点

在这里插入图片描述
关键点在于需要一个successor记录后驱节点:

    ListNode successor;// 记录后继节点

    // 反转以 head 为起点的 n 个节点,返回新的头节点
    public ListNode reverseN(ListNode head, int n) {
        // base case变成 n==1
        if (n == 1) {
            successor = head.next;
            return head;
        }
        ListNode last = reverseN(head.next, n - 1);
        head.next.next = head;
        head.next = successor;
        return last;
    }

3、反转链表的一部分

力扣第92题,反转链表Ⅱ
给定一个索引区间[m,n](索引从1开始),仅反转区间中的链表元素

[92]反转链表 II

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    // 题目等效以第left为头节点,反转前(right-left+1个)节点
    // 该函数的意思是,以head为头节点,反转[left,right]之间的节点,返回新的头节点
    public ListNode reverseBetween(ListNode head, int left, int right) {
        // base case
        if (left == 1) {
            // 相当于反转前n个节点
            return reverseN(head, right);
        }
        // 递归到新的链表上,保证元素对应位置相同
        head.next = reverseBetween(head.next, left - 1, right - 1);
        return head;
    }

    ListNode successor;// 后继节点

    // 返回反转头节点为head,反转前n个节点后的头节点
    ListNode reverseN(ListNode head, int n) {
        // base case
        if (n == 1) {
            successor = head.next;
            return head;
        }
        ListNode last = reverseN(head.next, n - 1);
        head.next.next = head;
        head.next = successor;
        return last;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值