转载请注明出处:http://blog.csdn.net/crazy1235/article/details/67632059
Subject
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,return 1->4->3->2->5->NULL.
Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
Explain
反转链表中第m 到 第n 个结点
解决方案就是通过链表反转的方式,将m-n个结点反转,然后在拼接之前后之后的结点。
重点就是记录第m个结点的前驱结点和第n个结点的后续结点。
链表反转的方法可参考:
http://blog.csdn.net/crazy1235/article/details/66971177
Solution
solution 1
还是通过栈的方式反转,然后拼接
/**
* 使用stack
*
* Runtime : 1ms
*
* beats 2.94% of java submissions
*
* @param head
* @param m
* @param n
* @return
*/
public ListNode reverseBetween(ListNode head, int m, int n) {
if (head == null || head.next == null || m >= n) {
return head;
}
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
head = dummyNode;
ListNode preNode = head; // pre node
for (int i = 1; i < m; i++) {
preNode = preNode.next;
}
// ----
ListNode tempNode = preNode.next;
Stack<ListNode> stack = new Stack<>();
int i = 0;
while (m + i <= n) {
stack.push(tempNode);
tempNode = tempNode.next;
i++;
}
ListNode postNode = tempNode; // post node
ListNode resultNode = stack.pop();
tempNode = resultNode;
while (!stack.isEmpty()) {
tempNode.next = stack.pop();
tempNode = tempNode.next;
}
//
preNode.next = resultNode;
tempNode.next = postNode;
return dummyNode.next;
}
solution 2
通过迭代方式
/**
* 通过迭代方式反转m-n的结点
*
* Runtime : 0ms
*
* beats 18.23% of java submissions
*
* @param head
* @param m
* @param n
* @return
*/
public ListNode reverseBetween2(ListNode head, int m, int n) {
if (head == null || head.next == null || m >= n) {
return head;
}
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
head = dummyNode;
ListNode preNode = head; // pre node
for (int i = 1; i < m; i++) {
preNode = preNode.next;
}
// iteration
ListNode nodeA = preNode.next;
ListNode nodeB = preNode.next.next;
ListNode nodeResult = nodeA;
int i = 0;
while (m + i < n) {
nodeA.next = nodeB.next;
nodeB.next = nodeResult;
nodeResult = nodeB;
nodeB = nodeA.next;
i++;
}
//
preNode.next = nodeResult;
return dummyNode.next;
}
此方法中不需要拼接第n个结点后面的结点,因为while循环之后,n后面的结点依旧是拼接完好的。
此方法还可以优化,省去nodeResult变量,将其替换为preNode.
/**
* 方法二的优化方式
*
* @param head
* @param m
* @param n
* @return
*/
public ListNode reverseBetween3(ListNode head, int m, int n) {
if (head == null || head.next == null || m >= n) {
return head;
}
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
head = dummyNode;
ListNode preNode = head; // pre node
for (int i = 1; i < m; i++) {
preNode = preNode.next;
}
ListNode nodeA = preNode.next;
ListNode nodeB = preNode.next.next;
for (int i = 0; i < n - m; i++) {
nodeA.next = nodeB.next;
nodeB.next = preNode.next;
preNode.next = nodeB;
nodeB = nodeA.next;
}
return dummyNode.next;
}
bingo~~