保研机试前的最后七道链表题

  1. 21. 合并两个有序链表 - 力扣(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* mergeTwoLists(ListNode* list1, ListNode* list2) {
            ListNode* head=new ListNode;
            ListNode* p=head;
            ListNode* res=head;
            while(list1 && list2){
                if(list1->val<=list2->val){
                    ListNode* temp=new ListNode;
                    p->next=temp;
                    temp->val=list1->val;
                    p=p->next;
                    list1=list1->next;
                }
                else{
                    ListNode* temp=new ListNode;
                    p->next=temp;
                    temp->val=list2->val;
                    p=p->next;
                    list2=list2->next;
                }
            }
            if(list1==nullptr && list2!=nullptr){
                p->next=list2;
            }
            else if(list1!=nullptr && list2==nullptr){
                p->next=list1;
            }
            return res->next;
        }
    };

    总结:当你需要创造一条新链表的时候,可以使用虚拟头结点简化边界情况的处理

  2. 86. 分隔链表 - 力扣(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* partition(ListNode* head, int x) {
            ListNode* head1=new ListNode;
            ListNode* res=head1;
            ListNode* head2=new ListNode;
            ListNode* res2=head2;
            ListNode* x_node=new ListNode;
            x_node->val=x;
            while(head){
                if(head->val<x){
                    ListNode* temp=new ListNode;
                    temp->val=head->val;
                    head1->next=temp;
                    head1=head1->next;
                }
                else{
                    ListNode* temp=new ListNode;
                    temp->val=head->val;
                    head2->next=temp;
                    head2=head2->next;
                }
                head=head->next;
            }
            head1->next=res2->next;
            return res->next;
        }
    };
  3. 23. 合并 K 个升序链表 - 力扣(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) {}
     * };
     */
    
    bool cmp(ListNode* p1,ListNode* p2){
        if(p1->val>p2->val){
            return true;
        }
        else{
            return false;
        }
    }
    class Solution {
    public:
        /*bool cmp(ListNode* p1,ListNode* p2){
            if(p1->val>p2->val){
                return true;
            }
            else{
                return false;
            }
        }*/
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            ListNode* head=new ListNode;//虚头节点
            ListNode* res=head;
            /*创建小根堆*/
            priority_queue<ListNode*,vector<ListNode*>,decltype(&cmp)> pq(cmp);
            /*将ListNode放入小根堆中*/
            int len=lists.size();
            for(int i=0;i<len;i++){
                if(lists[i]!=nullptr){
                    pq.push(lists[i]);
                }
            }
            /*开始循环*/
            while(!pq.empty()){
                ListNode* temp=pq.top();
                pq.pop();
                ListNode* node=new ListNode;
                node->val=temp->val;
                head->next=node;
                head=head->next;
                if(temp->next){
                    pq.push(temp->next);
                }
            }
            return res->next;
        }
    };

    用到 优先级队列(二叉堆),优先队列 pq 中的元素个数最多是 k,所以一次 poll 或者 add 方法的时间复杂度是 O(logk);所有的链表节点都会被加入和弹出 pq所以算法整体的时间复杂度是 O(Nlogk),其中 k 是链表的条数,N 是这些链表的节点总数

  4. 19. 删除链表的倒数第 N 个结点 - 力扣(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* removeNthFromEnd(ListNode* head, int n) {
            ListNode* dummy=new ListNode;
            dummy->next=head;
            ListNode* p1=head;
            ListNode* p2=dummy;
            /*p1向前走n步*/
            for(int i=1;i<=n;i++){
                p1=p1->next;
            }
            /*p1,p2一起向前走*/
            while(p1){
                p1=p1->next;
                p2=p2->next;
            }
            
            p2->next=p2->next->next;
            return dummy->next;
        }
    };

    虽然时间复杂度都是O(n),但是要感受一下双指针的用法

  5. 876. 链表的中间结点 - 力扣(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* middleNode(ListNode* head) {
            if(head->next==nullptr){return head;}
            if(head->next->next==nullptr){return head->next;}
            ListNode* fast=head;
            ListNode* slow=head;
            while(fast && fast->next){
                slow=slow->next;
                fast=fast->next->next;
            }
            return slow;
        }
    };

    感觉是上一道题的小喽啰

  6. 142. 环形链表 II - 力扣(LeetCode)

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode *detectCycle(ListNode *head) {
            if(head==nullptr || head->next==nullptr || head->next->next==nullptr){return nullptr;}
            bool flag=0;
            ListNode* fast=head;
            ListNode* slow=head;
            while(fast && fast->next && fast->next->next && slow && slow->next && slow->next->next){
                slow=slow->next;
                fast=fast->next->next;
                if(fast==slow){flag=1;break;}
            }
            if(flag==0){return nullptr;}
            slow=head;
            while(slow!=fast){
                slow=slow->next;
                fast=fast->next;
            }
            return slow;
        }
    };

    环形链表很好判断,这里就不写代码了(快慢指针最后相遇则有环),找终点的思路如下:首先找到快慢指针的相遇点,然后将慢指针返回起点,二者再次相遇的地方就是环形起始位置。

  7. 160. 相交链表 - 力扣(LeetCode)本题将用两个写法来写,第一种是用哈希法(回顾一下unordered_map的用法),第二种还是双指针用法(不太好想,p1先遍历A串,再遍历B串;p2先遍历B串,再遍历A串)                                                                                                  第一种写法:   

    /**
     * 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_map<ListNode*,bool> hmap;
            while(headA){
                hmap[headA]=1;
                headA=headA->next;
            }
            while(headB){
                if(hmap.find(headB)!=hmap.end()){
                    return headB;
                }
                headB=headB->next;
            }
            return nullptr;
        }
    };

    第二种写法:

    /**
     * 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) {
            ListNode* p1=headA;
            ListNode* p2=headB;
            //最后p1和p2都会为空
            while(p1!=p2){
                if(p1==nullptr){
                    p1=headB;
                }
                else{
                    p1=p1->next;
                }
                if(p2==nullptr){
                    p2=headA;
                }
                else{
                    p2=p2->next;
                }
            }
            if(p1==nullptr){return nullptr;}
            else{
                return p1;
            }
        }
    };

接下来更新5道链表思想题目,找找感觉~ 

看这里:五道链表习题,只过思路-CSDN博客

参考:

双指针技巧秒杀七道链表题目 | labuladong 的算法笔记c++优先队列(priority_queue)用法详解-CSDN博客c++优先队列priority_queue(自定义比较函数)_c++ priority_queue自定义比较函数-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值