2022-02-17Leetcode训练营_链表

天池训练营链接

天池leetcode训练营

移除链表元素

/**
 * 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值