题目
解题思路
个人感觉此题还是比较简单的,主要的方法就是:链表反转+链表合并。主要的思路:将中间要反转的链表前后断开,将链表反转之后,首部与原来的首部相连,尾部与原来尾部相连。
主要注意的点:
- 最好使用一个dummy指向head,防止题目反转第一个元素导致的nullPoint问题。
- 定义四个指针,left_point用来找到反转字符串的起始位置(左侧),right_point用来找到反转字符串的结束位置,left_list用来进行被反转链和左侧链的断链操作,记录左侧链最后元素,以便最后拼接,right_list的作用同left_list。断开后产生三条链,反转被反转链,此时,right_point是链表头部,left_point是链表尾部。
- 最后将三条链进行拼接,left_list连接right_point,left_point 连接right_list,完成最后的拼接,输出结果。
- 注意题目的要求,尽量一边扫描完成操作,所以在找left所指向的元素时不要直接定位到指定元素,走到其前一个位置停下就可以,把left_list定在这,然后left_point再向前走一步即可,这样就不用再重新走一遍链表找left_point的前一个元素了。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public static ListNode reversrList(ListNode head){
if(head==null) return null;
if(head.next==null) return head;
ListNode last=reversrList(head.next);
head.next.next=head;
head.next=null;
return last;
}
public ListNode reverseBetween(ListNode head, int left, int right) {
if(head.next==null) return head;
ListNode dummy=new ListNode(-1);
dummy.next=head;
ListNode left_point=dummy;
ListNode right_point=dummy;
int dis=right-left;
//部署两个两端指针
while(left>1){
left_point=left_point.next;
left--;
}
//保存到达左侧元素的前一个点,记录下来,为了后面断链使用
ListNode left_list=left_point;
//将left_point 继续向左移动到达指定位置
left_point=left_point.next;
right_point=left_point;
while(dis>0){
right_point=right_point.next;
dis--;
}
ListNode right_list=right_point.next;//可以忽略为null的情况
//断掉了与右边的链连接
right_point.next=null;
//断掉和左边的链
left_list.next=null;
//此时空间中有三条链,将要反转的链表进行反转
//此时完成对目标链表的反转
right_point=reversrList(left_point);
//下面进行三个链表的拼接
left_list.next=right_point;
left_point.next=right_list;
return dummy.next;//不要犯老毛病,不要直接用head,要用dummy.next
}
}