[LeetCode题解]92. 反转链表 II | 一次遍历 + 反转

解题思路

将链表分为三部分:[0, m)[m, n](n, L],其中 L 为链表长度。

第一步:使用虚拟头节点 dummy,用于将 head 也能参与操作;
第二步:找到第 m-1 节点(firstHalfEnd),用于连接反转后的第二部分链表;
第三步:遍历[m, n],进行链表反转。注意在反转前要保存待反转链表区间的第一个节点,用于连接第三部分链表;
第四步:

firstHalfEnd.next = pre;    // 此时的 pre 指向反转后的链表区间的第一个节点
secondHalfEnd.next = cur;   // 此时的 cur 指向第三部分链表的第一个节点,也就是第 n+1 个节点

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode ReverseBetween(ListNode head, int m, int n) {
        if(head == null || head.next == null || m == n) {
            return head;
        }

        ListNode dummy = new ListNode(0);
        dummy.next = head;

        ListNode cur = head;
        ListNode firstHalfEnd = dummy;
        for(int i = 1; i < m; i++) {
            firstHalfEnd = cur;
            cur = cur.next;
        }

        // 反转链表区间
        ListNode pre = null, secondHalfEnd = cur;
        for(int i = m; i <= n; i++) {
            var nextTmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nextTmp;
        }

        // 此时的 cur 指向第三部分的头节点
        firstHalfEnd.next = pre;
        secondHalfEnd.next = cur;
    
        return dummy.next;
    }
}

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 是链表的长度。一次遍历,因此时间复杂度为 \(O(n)\)
  • 空间复杂度:\(O(1)\)
posted @ 2020-11-20 23:44  大杂草  阅读(182)  评论(0编辑  收藏  举报