天池训练营链接
删除链表中的重复元素
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==nullptr || head->next ==nullptr) return head;
int v=head->val;
ListNode* cur=head->next;
ListNode* pre=head;
while(cur){
if(cur->val > v){
v=cur->val;
cur=cur->next;
pre=pre->next;
}
else{//删除cur
pre->next=cur->next;
cur=pre->next;
}
}
return head;
}
};
环形链表
思路1:题目给的最大节点数10000,所以遍历10000次,里面出现null就是无,否则有
思路2:unordered_set,把节点存进去,每扫一个,判断有没有在集合里出现过
思路3:两个节点都从head出发,快节点每次前进2个,慢节点每次前进1个,中间有交汇就是有环,快节点出null就是无环。
- 这个代码写的不好看,有时间改一下。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
//unordered_set可以处理,但有空间复杂度。
if(!head) return false;
//if(!head->next)
ListNode* cur=head;
while(cur){
if(!cur->next) return false;
if(!cur->next->next) return false;
cur = cur->next->next;
head=head->next;
if(cur==head) return true;
}
return false;
}
};
排序链表
官方题解文字部分不错,但代码不太好懂,
题解链接
要再回顾。加上自顶向下的解法
这个是自底向上解法:
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head==nullptr || head->next==nullptr) return head;
ListNode* dummyHead = new ListNode(0, head);
int length=0;
ListNode* node=head;
while(node!=nullptr){
++length;
node=node->next;
}
//算长度
//ListNode* pre=dummyHead, *cur=head;
for(int subLength=1; subLength<length; subLength<<=1){
//归并,从1开始,每次长度翻倍
ListNode* pre=dummyHead, *cur=dummyHead->next;
//这里,不能用head,head可能会排序换位,循环里面用dummy->next
while(cur!=nullptr){
//找归并的第一个链表
ListNode* head1=cur;
for(int i=1; i<subLength && cur->next!=nullptr; ++i){
cur=cur->next;
}
ListNode* head2=cur->next;
cur->next=nullptr;
cur=head2;
for(int i=1; i<subLength && cur!=nullptr &&cur->next!=nullptr; ++i){
cur=cur->next;
}
//归并的第二个链表头
ListNode* next=nullptr;
if(cur!=nullptr){
next=cur->next;//记录归并完的链表后面的下一个位置
cur->next=nullptr;//已归并的链表断掉尾
}
//后面还有要归并的,用cur记录一下位置,下一轮while处理
pre->next=merge(head1, head2);
//pre赋给已经归并的链表的末尾
while(pre->next != nullptr){
pre=pre->next;
}
cur=next;//cur更新到最新的头
}
}
return dummyHead->next;
}
ListNode* merge(ListNode* head1, ListNode* head2){
ListNode* dummyHead=new ListNode(0);
ListNode* temp=dummyHead, *temp1=head1, *temp2=head2;
//不用head往后走,用temp1,temp2比较好
//dummyHead固定头
while(temp1 != nullptr && temp2 != nullptr){
if(temp1->val <= temp2->val){
temp->next=temp1;
temp1=temp1->next;
temp=temp->next;
}
else{
temp->next=temp2;
temp2=temp2->next;
temp=temp->next;
}
}
if(temp1 == nullptr){
temp->next=temp2;
}
else if(temp2 == nullptr){
temp->next=temp1;
}
return dummyHead->next;
}
};
反转链表
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr || head->next==nullptr) return head;
ListNode* pre=nullptr, *cur=head;
ListNode* ans=new ListNode(0);
while(cur!=nullptr){
ans=cur;
ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return ans;//直接返回pre也可以
}
};
删除链表的倒数第 N 个结点
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//一趟扫描实现就不能先扫描看长度
//双指针一个指0,一个指n,然后两个同步往后移动
ListNode* dummyHead=new ListNode(0,head);
ListNode* first=dummyHead, *second=dummyHead;
while(n>0){
second=second->next;
n--;
}
while(second->next!=nullptr){
first=first->next;
second=second->next;
}
//删除first后面的
first->next=first->next->next;
return dummyHead->next;
}
};