【Leetcode】92. 反转链表 II

284 阅读2分钟

题目描述

在这里插入图片描述

// 92. 反转链表 II


// 给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。
// 请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

题解

// 本题可以借鉴【Leetcode】206. 反转链表 的方法。
// 假设left所在结点为leftHead,right所在结点为r,
// 我们需要找leftHead的前一个结点l,和r的后一个结点 rightTail,把
// leftHead和l断开连接,把r和rightTail断开连接,然后将中间从leftHead到
// r这段需要反转的链表用【Leetcode】206. 反转链表 方法进行翻转,
// 然后再把头尾接上即可。
//
// 首先head前面设一个虚拟头结点dummyHead,令l结点从dummyHead开始遍历,
// 因为left表示的是索引下标,而且是从1(一)开始计数的,而l指针是从head
// 前面的dummyHead开始计数的,所以相当于从0开始往上数,遍历到left-1之前即可
// 因为我们要的是left的前一个结点。
// 而r同理,r需要正好遍历到right结点,先将r初始化到此时的l位置,
// 然后从l开始遍历到right位置,就是从0遍历到right-left+1之前即可。
// 这样我们就得到了left的前一个位置l,和right位置的r结点。
// 我们真正要反转的区域就是l.next到r这个区域,令leftHead = l.next,
// 再取r的下一个结点为rightTail。
// 
// 之后我们将需要反转区域和链表切断连接,定义reverse函数,代码跟206.基本一样
// 不过我们这里不用返回什么东西。
//
// 反转之后,被反转区域的链表,原来的链表头leftHead会变成链表尾,
// 原来的链表尾r会变成链表头,让l.next与链表头r连接,
// 让链表尾leftHead与rightTail连接。最后返回整个大链表的头dummyHead.next
// 完成。
// 
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:35.8 MB, 在所有 Java 提交中击败了92.49%的用户
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
		if (left == right)
			return head;
		ListNode dummyHead = new ListNode(-1);
		dummyHead.next = head;
		ListNode l = dummyHead;
		for (int i = 0; i < left - 1; i++) {
            l = l.next;
        }
		ListNode r = l;
        for (int i = 0; i < right - left + 1; i++) {
            r = r.next;
        }
		
		ListNode leftHead = l.next;
		ListNode rightTail = r.next;
		l.next = null;
		r.next = null;
		
		reverse(leftHead);
		
		l.next = r;
		leftHead.next = rightTail;
		return dummyHead.next;
    }
	
	public void reverse(ListNode head) {
		if (head == null || head.next == null)
			return;
		ListNode pre = head;
		ListNode mid = head.next;
		ListNode cur = head.next.next;

		mid.next = pre;
		while (cur != null) {
			pre = mid;
			mid = cur;
			cur = cur.next;
			mid.next = pre;
		}	
	}
}