92. Reverse Linked List II (M)

本文探讨了链表从第m到n个元素的逆置算法,提供了两种实现方式:迭代和递归。迭代方法通过将链表分为三部分,分别处理左、中、右链表,实现一次遍历逆置;递归方法则通过设定两个指针,交换值并逐步向中间移动完成逆置。

Reverse Linked List II (M)

Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ mn ≤ length of list.

Example:

Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL

题意

将一链表从第m到n个元素逆置。

思路

206. Reverse Linked List 是全链表逆置,而本题只选择了部分链表逆置,同样使用迭代或递归。

迭代:将链表分为三个部分,左链表、待逆置的中间链表、右链表。记录左链表的尾结点和右链表的头结点,将中间链表逆置后再与左右链表相连。

递归:官方解答,利用递归找到待逆置链表的头尾结点,并设立指针left和right,每次交换两指针对应结点的值,并将两指针向中间移动。其中left由类成员变量控制(即全局变量),right由递归参数控制。实际上在最坏情况下,这种方法将链表遍历了两次,属于two-pass方法。


代码实现 - 迭代

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode left = null, right;		// left指向左链表尾结点,right指向右链表头结点
        ListNode newHead = null, newTail;	// 待逆置链表的头尾结点
        int count = 1;
        
        // 将left移动到左链表尾结点处
        while (count < m) {
            left = left == null ? head : left.next;
            count++;
        }
        
        newTail = left == null ? head : left.next;	   // 待逆置链表的头结点就是逆置后的尾结点
		right = newTail;
        // 在将right移动到右链表头结点的过程中,将中间链表逆置
        while (count <= n) {
            ListNode temp = right.next;
            right.next = newHead;
            newHead = right;
            right = temp;
            count++;
        }

        newTail.next = right;
        // 不存在左链表则不需要连接
        if (left != null) {
            left.next = newHead;
        }

        return m == 1 ? newHead : head;
    }
}

代码实现 - 递归

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    ListNode left;
    boolean stop;

    public ListNode reverseBetween(ListNode head, int m, int n) {
        left = head;
        stop = false;
        reverse(head, m, n);
        return head;
    }

    private void reverse(ListNode right, int m, int n) {
        // 边界,当前right已经在待逆置链表外
        if (n == 0) {
            return;
        }
        
        if (m > 1) {
            left = left.next;
        }
        reverse(right.next, m - 1, n - 1);
        
        // 当两指针相遇或者left跑到right右边时,无需再交换
        if (left == right || right.next == left) {
            stop = true;
        }
        
        if (!stop) {
            int temp = left.val;
            left.val = right.val;
            right.val = temp;
            left = left.next;
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值