question: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.
总结:
1.目的:将单链表从 m 到 n 进行翻转
2.思路:
a.设置一个 dummy 加到 给定 head 之前,先对 m 之前的进行遍历找到第 m 个节点;
b.将整个链表分为三部分,m之前的不管,m 到 n 的 翻转,n 以后的不管;
c.在for循环中,链表也分为三部分,其中中间部分不断伸长,每次取第三部分的第一个过来加到第三部分开始;
d.将三者连接
3.易错点:
a. 进行找m节点遍历时要判断下一个节点是否为空;
b.找m节点时 i 从1开始赋值而不是0;
1. 用第一个 for 循环,先遍历找到 m 节点,head不断后移,定义preNode指向 m 节点的前一个,令 m 前一个为最新的 head,定义 m 节点和 n 节点(第一次定义为同一个引用),此时 m = n 指向2,post 指向3;
2. 开始 for 循环,有 4 步。定义一个 temp 节点来储存暂时不调整的节点,即储存postNode 的下一个节点,此时 temp 指向4;
3. postNode.next = nNode,即将 3 的 next 指向2;
4. n 指向postNode 即指向3(后移一位);
5. 将postNode 指向之前 temp 储存的节点4,判断条件继续循环,此时为 dummy—1 3—2 4—5—6;
6. temp储存postNode 的下一个节点,指向5;
7. postNode.next = nNode ,即将 4 的next 指向 3;
8. n 指向postNode 即指向 4 (继续后移一位);
9. 将postNode 指向之前 temp 储存的节点5,判断条件断开循环,此时为 dummy—1 4—3—2 5—6;
将三个片段连接即可
head.next = nNode;
mNode.next = postNode;
代码如下:
/**
* Definition for ListNode
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* @param ListNode head is the head of the linked list
* @oaram m and n
* @return: The head of the reversed ListNode
*/
public ListNode reverseBetween(ListNode head, int m , int n) {
if(head == null || m >= n){
return head;
}
ListNode dummy = new ListNode(0);
dummy.next = head;
head = dummy;
for(int i = 1;i < m; i++){
if(head == null){ // I forget this
return null;
}
head = head.next;
}
ListNode preNode = head;
ListNode mNode = head.next;
ListNode nNode = head.next;
ListNode postNode = mNode.next;
for(int i = m;i < n;i++){
ListNode temp = postNode.next;
postNode.next = nNode;
nNode = postNode;
postNode = temp;
}
mNode.next = postNode;
preNode.next = nNode; //head.next = nNode 也可以
return dummy.next;
}
}
代码部分参考于九章算法lintcode答案