反转链表相关的高频题:
【来不及刷题之】6、反转链表(迭代、递归)_vector<>的博客-CSDN博客
【来不及刷题之】7、K个一组翻转链表(双指针)_将一个vector分为k个一组_vector<>的博客-CSDN博客
java
关键点:
- 要简单快捷地找到preStart和nextEnd以及start和end四个指针
- 一定要有dummy结点,因为会有从头到尾全部反转的情况,如果没有dummy结点,就找不到preStart了。
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode preStart=null, start=null, end=null, nextEnd=null, p=dummy; // 注意p指向的是dummy
int i=0;
while(p!=null){
if(i==left-1){
preStart=p;
start=preStart.next;
}
if(i==right){
end=p;
nextEnd=end.next;
break;
}
i++;
p=p.next;
}
preStart.next=null;
end.next=null;
ListNode newHead=reverse(start);
start.next=nextEnd;
preStart.next=end;
return dummy.next;
}
ListNode reverse(ListNode head){
if(head==null || head.next==null) // 注意这里递归退出的条件是两个
return head;
ListNode newHead=reverse(head.next);
head.next.next=head;
head.next=null;
return newHead;
}
}
c++
虽然时间复杂度,空间复杂度都不怎么样,好歹是自己写出来的
ListNode* reverseBetween(ListNode* head, int left, int right) {
//创建头结点
//标记第n+1个结点
//标记第n个结点,并从n结点处断开
//标记第m个结点,以便后续的连接工作
//以m-1个结点为头结点,进行头插
//将剩下的结点连接到链表尾部(表尾是原来的m处)
if(head->next==nullptr||left==right)return head;
ListNode* Dummy=new ListNode();//头结点
Dummy->next=head;
ListNode* m=nullptr;
ListNode* n=nullptr;
ListNode* m_1=Dummy;
ListNode* n_1=nullptr;//m_1是m-1,n_1是n+1;
int k=left;
while(k-1!=0){
m_1=m_1->next;
k--;
}
m=m_1->next;//m_1是待翻转链表的头结点,m是链表反转后的尾结点
n=m;
while(right!=left){
n=n->next;
right--;
}
n_1=n->next;//n是待翻转链表的尾结点,n_1是后序链表的头结点
n->next=nullptr;//断开
//初始化完毕,开始翻转
m_1=reverse(m_1);
//将翻转后的链表和尾巴连起来
m->next=n_1;
return Dummy->next ;
}
ListNode* reverse(ListNode* head){//头插法翻转
ListNode* p=nullptr;
ListNode* q=nullptr;
p=head->next;
head->next=nullptr;
while(p!=nullptr){
q=p->next;
p->next=head->next;
head->next=p;
p=q;
}
return head;
}