首页 > 其他 > 详细

递归解决反转链表的一部分

时间:2020-04-22 14:06:58      阅读:64      评论:0      收藏:0      [点我收藏+]

技术分享图片

迭代思想:

先用一个 for 循环找到第 m 个位置,然后再用一个 for 循环将 m 和 n 之间的元素反转。但是我们的递归解法不用一个 for 循环,纯递归实现反转。
迭代实现思路看起来虽然简单,但是细节问题很多的,反而不容易写对。相反,递归实现就很简洁优美,下面就由浅入深,先从反转整个单链表说起。

递归反转整个链表

ListNode reverse(ListNode head) {
    if (head.next == null) return head;
    //last是反转后的头结点
    ListNode last = reverse(head.next);
    
    head.next.next = head;
    head.next = null;
    return last;
}

上述代码是不是优雅有难以理解?

  1. 想要理解递归代码,首先要明确递归的定义
  2. 遇到递归千万不要把思维跳进递归栈里,你的脑子够想几层递归
  3. 而是要思考该递归执行完成的结果是什么(根据定义)

语句解析:

技术分享图片
技术分享图片
技术分享图片
技术分享图片

反转前n个节点

ListNode successor = null; // 后驱节点

// 反转以 head 为起点的 n 个节点,返回新的头结点
ListNode reverseN(ListNode head, int n) {
    if (n == 1) { 
        // 记录第 n + 1 个节点
        successor = head.next;
        return head;
    }
    // 以 head.next 为起点,需要反转前 n - 1 个节点
    ListNode last = reverseN(head.next, n - 1);

    head.next.next = head;
    // 让反转之后的 head 节点和后面的节点连起来
    head.next = successor;
    return last;
}

为什么要加successor呢?

现在 head 节点在递归反转之后不一定是最后一个节点了,所以要记录后驱 successor(第 n + 1 个节点),反转之后将 head 连接上。

反转链表的一部分

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;
}

递归解决反转链表的一部分

原文:https://www.cnblogs.com/treasury/p/12751395.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!