本解题方法可能有点啰嗦,也不是最优解法,但是我自认为还是比较好理解的。
题目描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
解题思路:
- 首先我们需要写出一个能反转整个链表的工具方法。
- 然后开始判断需要反转的链表是哪一部分。共分为四种情况。先算出链表的长度:count
- 第一种情况:要反转的链表刚好是原链表(m == 1 && n == count)
- 第二种情况:要反转的链表和原链表的头节点相同,尾节点不同(m == 1 && n < count)
- 第三种情况:要反转的链表和原链表的头节点不同,尾节点相同 (m > 1 && n == count)
- 第四种情况:要反转的链表和原链表的头节点、尾节点均不相同(m > 1 && n < count)
- 根据以上四种情况。找到左边不需要反转的链表的尾节点,需要反转的链表的头节点,,右边不需要反转的链表的头节点。反转后链表的尾节点。然后将他们连接起来。
- 返回最终链表的头节点。
解题代码:
public static ListNode reverseNode(ListNode head) { //反转全部链表
if (head == null || head.next == null) {
return head;
}
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode f = head;
ListNode s = f.next;
while (s != null) {
f.next = s.next;
s.next = dummyHead.next;
dummyHead.next = s;
s = f.next;
}
return dummyHead.next;
}
public static ListNode reverseBetween(ListNode head, int m, int n) {
if (head == null || head.next == null) {
return head;
}
//计算链表的长度
int count = 0;
ListNode t = head;
while (t != null) {
count++;
t = t.next;
}
ListNode dummyHead = head;
if (m == 1 && n == count) {
return reverseNode(head);
}else if (m == 1 && n < count) {
//找到需要反转的链表的尾节点
ListNode temp = dummyHead;
for (int i = 0; i < n-m; i++) {
temp = temp.next;
}
//找到右边不需要反转的链表的头节点
ListNode secondHead = temp.next;
temp.next = null;
dummyHead = reverseNode(dummyHead);
//找到反转后链表的尾节点
ListNode newNode = dummyHead;
while (newNode != null) {
if (newNode.next == null) {
break;
}
newNode = newNode.next;
}
//将反转后的链表跟右边没有反转的链表连接起来
newNode.next = secondHead;
return dummyHead;
}else if (m > 1 && n == count) {
ListNode firstTailNode = dummyHead;
for (int i = 1; i < m-1; i++) {
firstTailNode = firstTailNode.next;
}
//找到需要反转的链表的头节点
ListNode reverseHead = firstTailNode.next;
firstTailNode.next = null;
reverseHead = reverseNode(reverseHead);
//将左边不需要反转的链表跟反转后的链表连起来。
firstTailNode.next = reverseHead;
return head;
}else {
//找到左边不用反转的链表的尾节点firstTailNode。
ListNode firstTailNode = dummyHead;
for (int i = 1; i < m-1; i++) {
firstTailNode = firstTailNode.next;
}
//找到需要反转的链表的头节点
ListNode reverseHead = firstTailNode.next;
firstTailNode.next = null;
ListNode temp = reverseHead;
//找到需要反转的链表的尾节点
for (int i = 0; i < n-m; i++) {
temp = temp.next;
}
//如果需要反转的链表的尾节点是整个链表的尾节点
if (temp.next == null) {
reverseHead = reverseNode(reverseHead);
firstTailNode.next = reverseHead;
return head;
}else {
//找到右边不用反转的链表的头节点
ListNode secondHead = temp.next;
temp.next = null;
reverseHead = reverseNode(reverseHead);
//找到反转后链表的尾节点
ListNode newNode = reverseHead;
while (reverseHead != null) {
if (reverseHead.next == null) {
break;
}
reverseHead = reverseHead.next;
}
//反转后的链表接上后面的链表
reverseHead.next = secondHead;
//前面的链表接上反转后的链表
firstTailNode.next = newNode;
return head;
}
}
}