1.反转链表中的第m至第n个节点题目:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
1.1 算法思路
有四个关键的位置需要记录:第m个节点及其前驱节点、第n个节点及其后继节点。
对整个链表遍历,将链表head的头指针向后移动m-1个节点,即为第m个节点,记其前驱节点为pre;
自第m个节点开始逆置changLen = n-m+1个节点,即将第m至第n个节点依次反转,并记录下来反转后的头结点reversedListHead和尾节点reversedListTail;
将反转后的尾节点reversedListTail的Next域与第n个节点的后继节点head连接,pre节点的Next域与reversedListHead连接。
1.2 代码实现
// 节点
class Node{
int val;
Node pre;
Node next;
}
// 反转链表中的第m至第n个节点
public Node reverseBetween(Node head, int m, int n){
int changeLen = n-m+1; // 需要逆置的节点数
Node pre = null; // 开始逆置节点的前驱节点
Node result = head; // 记录最开始的头节点,也是逆置之后的链表的头节点
int move = m-1; // head后移m-1个位置,到达第m个节点
// 循环完后,pre指向第m个节点的前驱节点,head指向第m个节点
while(head != null && move >0){
pre = head;
head = head.next;
move--;
}
Node reversedListTail = head; // 此时reversedListTail指向第m个节点
Node reversedListHead = null; // reversedListHead记录需翻转的链表片段的头节点
while(head != null && changeLen > 0){
Node next = head.next;
head.next = reversedListHead;
reversedListHead = head;
head = next;
changeLen--;
}
reversedListTail.next = head; // 连接逆置后的链表尾与逆置段的后一个节点,翻转后的尾节点指向第n个节点的下一个节点
// 最后需要考虑翻转片段链表,翻转后的头节点是原始链表的头节点,还是中间节点,通过pre判断
if(pre !=null){
pre.next = reversedListHead; // 如果pre不为空,说明不是从第1个节点开始逆置的,即m > 1。将逆置链表开始的节点前驱与逆置后的头结点连接起来
}else{
result = reversedListHead; // 如果pre为空,说明m=1,即从第1个节点开始逆置,结果即为逆置后的头结点
}
return result;
}