解法一:区间部分前驱插入
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
if (head == null || head.next == null || m == n) {
return head;
}
// find sublist from m to n
ListNode headOfSubList = head;
ListNode endOfSubList = head;
ListNode prevOfInsert = new ListNode(-1);
prevOfInsert.next = head;
int i = 1;
int j = 1;
while (i < m) {
i++;
prevOfInsert = prevOfInsert.next;
headOfSubList = headOfSubList.next;
}
while (j < n) {
j++;
endOfSubList = endOfSubList.next;
}
ListNode nextOfInsert = endOfSubList.next;
// exclude sub list from original list
prevOfInsert.next = nextOfInsert;
endOfSubList.next = null;
// insert sub list to original list
ListNode toBeInsert = null;
while (headOfSubList != null) {
toBeInsert = headOfSubList;
headOfSubList = headOfSubList.next;
// insert first node of sub list to original list
toBeInsert.next = nextOfInsert;
prevOfInsert.next = toBeInsert;
nextOfInsert = toBeInsert;
}
// if m == 1, then "toBeInsert" is the first node of the list
if (m == 1) {
return toBeInsert;
}
return head;
}
}
1.1.解题思路:
- 先找到需要反转的区间,同时标记区间前后的两个节点
- 将需要反转的区间从原链表中分离
- 把需要反转的区间逐个倒着插入原来的链表
1.2.解题图解:
1.先找到需要反转的区间,同时标记区间前后的两个节点,也就是4个节点
2.将需要反转的区间从原链表中分离
3.把需要反转的区间逐个倒着插入原来的链表
3.1先Sublist中的第一个节点
3.2插入作为endOfSubList的前驱节点
3.3将nextOfInsert节点重新赋值,那么下一个节点就将插入在1和2之间
3.4完成sublist为空,停止循环
1.3.Corner case
1. m = n or head is null or list have only one node
if (head == null || head.next == null || m == n) {
return head;
}
2.node m is the head node
if (m == 1) {
return toBeInsert;
}
其他情况,比如list have only two node or list have more that 2 nodes or node n is the last node都能被代码覆盖,不属于corner case
解法二:借助栈
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
public ListNode reverseBetween (ListNode head, int m, int n) {
if (head == null || head.next == null || m == n) {
return head;
}
// find Node n, and push nodes from m to n to stack
ListNode nNode = head;
ListNode prevOfInsert = new ListNode(-1);
prevOfInsert.next = head;
int i = 1;
int j = m;
while (i < m) {
i++;
prevOfInsert = prevOfInsert.next;
nNode = nNode.next;
}
Stack<ListNode> backup = new Stack<ListNode>();
while (j < n) {
j++;
backup.push(nNode);
nNode = nNode.next;
}
backup.push(nNode);
ListNode nextOfInsert = nNode.next;
// exclude sub list from original list
prevOfInsert.next = nextOfInsert;
nNode.next = null;
// insert elements from stack to original list
ListNode toBeInsert = null;
while (!backup.empty()) {
toBeInsert = backup.pop();
toBeInsert.next = nextOfInsert;
prevOfInsert.next = toBeInsert;
prevOfInsert = toBeInsert;
}
// if m == 1, then "nNode" is the last node of original sublist, also the first node of the reversed list
if (m == 1) {
return nNode;
}
return head;
}
}
2.1.解题思路:
- 先找到需要反转的区间,把节点m和节点n及其之间的所有节点放入栈中,同时标记区间前后的两个节点
- 将需要反转的区间从原链表中分离
- 把栈中的元素逐个取出,顺序插入原来的链表
2.2.解题图解:
- 先找到需要反转的区间,把节点m和节点n及其之间的所有节点放入栈中,同时标记区间前后的两个节点
- 将需要反转的区间从原链表中分离
- 把栈中的元素逐个取出,顺序插入原来的链表
- 向前移动prevOfInsert
2.3.Corner case
node m is the head node,nNode就是需要反转的sublist中最后一个节点,反转之后成为sublist的第一个节点, 也是整个链表的第一个节点

京公网安备 11010502036488号