import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
// 算法时间复杂度O(N),额外空间复杂度O(1)
// 1.先定义两个指针start和end,分别指向前方的m位置和后方的n位置
ListNode start = null;
ListNode end = null;
// 2.记录start指针的上一个结点allPre,end指针的下一个结点allPost
ListNode allPre = head; // 先把allPre指向head这个整个链表的起点,随着查找m可以往后移动head
ListNode allPost = null;
// 准备找到m和n位置对应的start和end,以及对应的allPre和allPost
ListNode cur = head;
for (int i = 1; cur != null; cur = cur.next, i++) {
if (i == m) {
start = cur;
}
if (i == n) {
end = cur;
allPost = end.next;
break;
}
// 只有在i>1(让allPre落后一位)且i<m(还没找到start)时更新allPre
if (i > 1 && i < m) {
allPre = allPre.next;
}
}
System.out.println("allPre: " + (allPre != null ? allPre.val : "null"));
System.out.println("start: " + (start != null ? start.val : "null"));
System.out.println("end: " + (end != null ? end.val : "null"));
System.out.println("allPost: " + (allPost != null ? allPost.val : "null"));
// 3.执行类似于上一题的方法,反转start和end之间的链表,返回反转后的起点newStart和终点newEnd
ListNode newStart = end;
ListNode newEnd = start;
// 只有strat和end不指向同一个结点(反转区间>1)时,才有反转的必要
if (start != end) {
ListNode newPre = start;
ListNode newCur = start.next;
ListNode newNext = newCur.next;
// 此处不用管newPre的next指向何方,因为这个newPre就是newEnd,是数组反转后的结尾,下文会令其指向allPost
while(newCur != allPost) {
newNext = newCur.next;
newCur.next = newPre;
System.out.println("结点" + newCur.val + "的反转已完成");
newPre = newCur;
newCur = newNext;
}
}
// 4.令allPre指向newStart,令allPost指向newEnd
// 注意allPre的边界判断!allPre可能与newEnd(start)重合!
if (allPre == newEnd) {
// 如果allPre 跟 newEnd(start) 是同一个结点(m=1的情况),说明start前面没有任何元素,这时可以直接移动head到链表区间反转后的起点,令head = newStart
allPre = newStart;
head = allPre;
} else {
// 否则,是正常情况,令allPre指向newStart,从newStart到newEnd是反转区间
allPre.next = newStart;
}
newEnd.next = allPost;
System.out.println("newEnd结点" + newEnd.val + "的下一个结点allPost是" + (allPost != null ? allPost.val : "null"));
System.out.println("allPre结点" + allPre.val + "的下一个结点newStart是" + (newStart != null ? newStart.val : "null"));
System.out.println("head结点" + head.val);
return head;
}
}