问题来源:选自LeetCode 92:反转链表 II
问题描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
题目给定信息:
问题分析:
这道题也是要求实现链表的逆序,但是不同的地方在于要求在链表中规定的某一部分实现链表的逆序。那么我们可以把这个链表分为三部分:待逆序链表的前面是一部分、需要逆序的链表是一部分、待逆序链表的后面是一部分。我们只需要找到逆序链表的开始节点以及这个开始节点的前一个节点,再找到待逆序部分的最后一个节点以及该节点的后继节点。当我们把带逆序部分逆序完成之后在拼接起来就完成题目要求了。
函数实现:
1 public ListNode reverseBetween(ListNode head, int m, int n) { 2 //确定链表中需要逆置部分的长度 3 int move_len = n - m + 1; 4 // 逆置开始节点的前驱节点 5 ListNode pre_head = null; 6 // 逆置完成后结果链表的头指针 7 ListNode result = head; 8 // 通过for循环找到逆置开始节点的前一个节点 9 for(int i=1;i<m;i++){ 10 pre_head = head; 11 head = head.next; 12 } 13 //经过上面的循环此时的head指向的就是当前需要逆置的链表的开头节点 14 //用一个变量保存当前需要逆置的链表未逆置前的开头节点 15 ListNode modify_list_head=head; 16 ListNode new_head=null; 17 //这一部分循环完成了逆置部分的逆置过程 18 while(head!=null&&move_len!=0){ 19 ListNode next=head.next; 20 head.next=new_head; 21 new_head=head; 22 head=next; 23 move_len--; 24 } 25 //此时的head指向的是需要逆置部分的末尾节点的后继节点 26 modify_list_head.next=head; 27 //如果需要逆置部分的节点的前驱节点为空,说明是从头开始逆置的 28 if(pre_head==null){ 29 result=new_head; 30 }else{ 31 //如果需要逆置部分的节点的前驱节点不为空,直接用前驱节点的指针指向逆置部分的头节点即可 32 pre_head.next=new_head; 33 } 34 return result; 35 }
运行结果: