链表专题
- 目前还没解决 遍历到null->next咋办
- Leetcode148待做
- 当头结点可能被修改时:
auto dummy=new ListNode(-1,head);
注意一定要把head串上去 - 找链表上倒数第n个数
auto first=dummy,second=dummy;
for(int i=0;i<n;i++)first=first->next;
走n步
first=first->next;
while(first->next){
//结束后,first位于最后一个接点,second处于倒数第n+1节点
first=first->next;
second=second->next;
}
- 发现一般都是while(cur)
因为while(cur->next)对空链表不适合
Leetcode19.删除链表的倒数第 N 个结点(模板)
Leetcode237删除链表中的节点(思路巧妙)
Leetcode83.删除排序链表中的重复元素
Leetcode61.旋转链表(模板-倒数第n个节点)
Leetcode24.两两交换链表中的节点(思路巧妙自己做还没做出来)
Leetcode206.反转链表(上一题的变题)
Leetcode92.反转链表 II(上一题的变题)
Leetcode160.相交链表(数学题-思路巧妙)
Leetcode142.环形链表 II(数学题-思路巧妙)
Leetcode148.排序链表(呜呜不会做)
一、Leetcode19.删除链表的倒数第 N 个结点.
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* removeNthFromEnd(ListNode* head, int n) {
auto dummy=new ListNode(-1,head);
auto first=dummy,second=dummy;
for(int i=0;i<n;i++){
first=first->next;
}
while(first->next){
first=first->next;
second=second->next;
}
second->next=second->next->next;
return dummy->next;
}
二、Leetcode237删除链表中的节点.
请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。
题目数据保证需要删除的节点 不是末尾节点 。
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
void deleteNode(ListNode* node) {
node->val=node->next->val;
node->next=node->next->next;
}
三、Leetcode83.删除排序链表中的重复元素.
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* deleteDuplicates(ListNode* head) {
auto cur=head;
while(cur){
if(cur->next&&cur->val==cur->next->val)cur->next=cur->next->next;
else cur=cur->next;
}
return head;
}
四、Leetcode61.旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* rotateRight(ListNode* head, int k) {
int n=0;
auto cur=head;
while(cur){
cur=cur->next;
n++;
}
if(n==0)return head;
k%=n;
auto first=head,second=head;
for(int i=0;i<k;i++){
first=first->next;
}
while(first->next){
first=first->next;
second=second->next;
}
first->next=head;
head=second->next;
second->next=NULL;
return head;
}
五、Leetcode24.两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* swapPairs(ListNode* head) {
auto dummy=new ListNode(-1);
dummy->next=head;
for(auto p=dummy;p->next&&p->next->next;){
auto a=p->next;
auto b=a->next;
p->next=b;
a->next=b->next;
b->next=a;
p=a;
}
return dummy->next;
}
六、Leetcode206.反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* reverseList(ListNode* head) {
if(!head)return NULL;
auto a=head;
auto b=head->next;
while(b!=NULL){
auto c=b->next;
b->next=a;
a=b;
b=c;
}
head->next=NULL;
return a;
}
七、Leetcode92.反转链表 II
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(left==right)return head;
auto dummy=new ListNode(-1);
dummy->next=head;
auto a=dummy;auto c=dummy;
for(int i=0;i<left-1;i++)a=a->next;
for(int i=0;i<right;i++)c=c->next;
auto d=c->next;
auto b=a->next;
for(auto p=a->next,q=p->next;q!=d;){
auto qq=q->next;
q->next=p;
p=q;
q=qq;
}
a->next=c;
b->next=d;
return dummy->next;
}
八、Leetcode160.相交链表.
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto p=headA;
auto q=headB;
while(p!=q){
if(p)p=p->next;
else p=headB;
if(q)q=q->next;
else q=headA;
}
return q;
}
九、Leetcode142.环形链表 II.
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode *detectCycle(ListNode *head) {
auto fast=head;
auto slow=head;
while(fast){
fast=fast->next;
slow=slow->next;
if(fast)fast=fast->next;
else break;
if(fast==slow){
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}
十、Leetcode148.排序链表.
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* sortList(ListNode* head) {
auto dummy=new ListNode(-1);
dummy->next=head;
int n=0;
for(auto p=head;p;p=p->next)n++;
for(int i=1;i<n;i=i*2){
auto cur=dummy;
for(int j=0;j+i<n;j+=i*2){
auto left=cur->next,right=cur->next;
for(int k=0;k<i;k++)right=right->next;
int l=0,r=0;
while(l<i&&r<i&&right){
if(left->val<=right->val){
cur->next=left;
cur=left;
left=left->next;
l++;
}else{
cur->next=right;
cur=right;
right=right->next;
r++;
}
}
while(l<i){
cur->next=left;
cur=left;
left=left->next;
l++;
}
while(r<i&&right){
cur->next=right;
cur=right;
right=right->next;
r++;
}
cur->next=right;
}
}
return dummy->next;
}