题目1
92. 反转链表 II【中等】
题解
方法一:直接反转
(思路对了,但是有几点模糊因此没有ac,如:虚拟头结点,找 left,right 到底找哪个结点) 具体解法如下:
- 找到 left前一个结点和 right结点
- 要反转的部分和不用反转的部分断开
- 要反转的部分反转
- 要反转的部分的不用反转的部分接上
class Solution {
public void reverse(ListNode head){
ListNode pre=null,curr=head;
while(curr!=null){
ListNode r=curr.next;
curr.next=pre;
pre=curr;
curr=r;
}
}
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummyHead=new ListNode();
dummyHead.next=head;
ListNode p=dummyHead,q=dummyHead;
int i=1,j=1;
while(j<=right){
if(i<left){
p=p.next;
i++;
}
q=q.next;
j++;
}
ListNode first=p.next;
ListNode last=q.next;
p.next=null;
q.next=null;
reverse(first);
p.next=q;
first.next=last;
return dummyHead.next;
}
}
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
方法二:头插法反转
这种方法的原因是:如果方法一中 left 和 right 离得特别远,比如在头和尾,那么找到 right 位置就会耗费一定时间,但是这种时间是不必要的(本来直接反转就行),因此需要改进
头插法反转的示意图如下面三张图: 头插穿针引线: 拉直后效果图:curr自动往后移动一位
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummyHead=new ListNode();
dummyHead.next=head;
ListNode p=dummyHead;
for(int i=1;i<left;i++)
p=p.next;
ListNode curr=p.next;
for(int j=left;j<right;j++){
ListNode r=curr.next;
curr.next=r.next;
r.next=p.next;
p.next=r;
}
return dummyHead.next;
}
}
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
注意:要学会 虚拟头结点 的用法!很有用!
|