天池训练营链接
移除链表元素
/**
* 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* removeElements(ListNode* head, int val) {
//这里的head是第一个节点的意思,所以可在前面再加一个节点
ListNode *hNode = new ListNode(-1);
hNode->next = head;
ListNode* pre = hNode;
while(pre->next != nullptr){
if(pre->next->val == val){
pre->next = pre->next->next;
continue;
//注意这个continue,一次只判断一个,判断pre->next
}
pre=pre->next;
}
return hNode->next;
}
};
旋转链表
参考题解
扫一遍记录节点个数和尾节点指针
k=k%n
把后k个搬到前面来,扫到第n-k-1个节点cur,cur->next当头,tail->next是原head
/**
* 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* rotateRight(ListNode* head, int k) {
int len=0;
if(head == nullptr) return head;
if(head->next == nullptr) return head;
ListNode* tail=head;
while(tail->next){
len+=1;
tail=tail->next;
}
//tail=tail->next;//尾节点
len+=1;//节点个数
k=k%len;
ListNode* cur=head;
for(int i=0; i<len-k-1; ++i){
cur=cur->next;
}
tail->next=head;
head=cur->next;//这题得加后两句,不能把链表直接变环
cur->next=nullptr;
return head;
}
};
合并两个有序链表
个人解答:
输入:[1,2,4]
[1,3,4]
输出:[4]
答案错误
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head= new ListNode();
if(list1 == nullptr) return list2;
if(list2 == nullptr) return list1;
while(list1!=nullptr && list2 != nullptr){
if(list1->val < list2->val){
head->next = list1;
list1=list1->next;
}
else{
head->next=list2;
list2=list2->next;
}
head = head->next;
}
if(list1==nullptr){
head->next=list2;
}
if(list2==nullptr){
head->next=list1;
}
return head->next;
}
};
改进:
错误位置在于返回head是移动以后的,而没有提前存下来头结点,这里增加HNode记录头结点。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head= new ListNode(-1);
ListNode* HNode = head;
if(list1 == nullptr) return list2;
if(list2 == nullptr) return list1;
while(list1!=nullptr && list2 != nullptr){
if(list1->val <= list2->val){
head->next = list1;
list1=list1->next;
}
else{
head->next=list2;
list2=list2->next;
}
head = head->next;
}
if(list1==nullptr){
head->next=list2;
}
if(list2==nullptr){
head->next=list1;
}
return HNode->next;
}
};
相交链表
双指针暴力解法
先分别扫一遍,确定两个链表长度lenA,lenB,确保A是更长的,如果A短,就交换headA,headB
lenA,lenB的差值step,A的指针往前先移动step步,两条链表对齐
然后两个指针同时移动,指向的节点相同的时候就相交,同时指向null就返回null
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==nullptr || headB==nullptr) return nullptr;
int lenA=0,lenB=0;
ListNode *curA=headA;
ListNode *curB=headB;
while(curA){
lenA+=1;
curA=curA->next;
}
while(curB){
lenB+=1;
curB=curB->next;
}
if(lenA<lenB){
swap(headA, headB);//保证headA指向更长的
}
int step=abs(lenA-lenB);//headA移动几个
while(step>0){
headA=headA->next;
step-=1;
}
while(headA!=nullptr && headB!=nullptr){
if(headA == headB){
return headA;
}
else{
headA=headA->next;
headB=headB->next;
}
}
return nullptr;
}
};
哈希集合,把A先存入哈希集合,然后对B里面每个节点,用count判断有没有在集合里面
这个方法空间复杂度比较大。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> s;
while(headA){
s.insert(headA);
headA=headA->next;
}
while(headB){
if(s.count(headB)) return headB;
else headB=headB->next;
}
return nullptr;
}
};
删除排序链表中的重复元素 II
/**
* 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;
ListNode* HNode=new ListNode(-1);
HNode->next=head;
//前面加个头节点
ListNode* pre=HNode;//pre是当前判断的节点前面一个节点,如果当前节点要删除,就赋值到pre->next
ListNode* cur=head;
//2个指针
while(cur!=nullptr){
if(cur->next == nullptr) break;//没有下一个节点一定不是重复
if(cur->val<cur->next->val){//不重复就双指针同时往后移动
pre=pre->next;
cur=cur->next;
}
else{
ListNode* temp=cur;//这句不需要
int v=cur->val;//记录这个重复的值
while(cur!=nullptr && cur->val==v){//值等于这个数的都删掉,直接next
cur=cur->next;
}
pre->next=cur;//cur现在是重复的过去以后的位置,pre->next指向它
}
}
return HNode->next;
}
};
知识
unordered_set.count(a) 返回set里面出现了多少次a