LeetCode算法讲解——链表

记录LeetCode算法讲解经典版,涉及相关数据结构和算法的经典题目及相关题目解题思想和代码实现。

一、预备知识

在这里插入图片描述
在这里插入图片描述

二、例题

例1-a、链表逆序(easy)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *new_head=NULL;
        ListNode *q;
        while(head!=NULL){
            q = head->next;
            head->next=new_head;
            new_head = head;
            head=q;
        }
        return new_head;
    }
};

例1-b、链表逆序2(medium)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
   ListNode* reverseBetween(ListNode* head, int m, int n) {
       ListNode* result = head;
       int number = n-m+1;
       ListNode* pre_head = NULL;
       //找到pre_head和head:head指向m位置,pre_head指向m前一个
       while(head&&--m){
           pre_head = head;
           head=head->next;
       }
       //modify_list_tail指向反向链表的尾节点
       ListNode* modify_list_tail = head;
       //new_head指向反转链表的头节点;
       ListNode* new_head = NULL;
       while(head&&number){
           ListNode* q = head->next;
           head->next = new_head;
           new_head=head;
           head = q;
           number--;
       }
       modify_list_tail->next = head;
       if(pre_head){
           pre_head->next = new_head;          
       }else{
       /*m=1的情况,没有pre_head*/
           result = new_head;
       }
       return result;
   }
};

例2、链表求交点(easy)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:

方法一:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
#include<set>
using namespace std;
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        set<ListNode *> se;//用于保存headA各个节点地址的set
        // 把headA为头节点的链表各个节点放入set
        while(headA){
            se.insert(headA);
            headA = headA->next;
        }
        // 查找headB的各个头节点是否在set中
        while(headB){
            if(se.find(headB)!=se.end()){
                return headB;
            }
            headB=headB->next;
        }
        return 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) {
       int lenA = 0;
       int lenB = 0;
       ListNode* A = headA;
       ListNode* B = headB;
       while(A){
           A = A->next;
           lenA++;
       }
       while(B){
           B = B->next;
           lenB++;
       }
       if(lenB>=lenA){
           int temp = lenB-lenA;
           while(temp){
               headB=headB->next;
               temp--;
           }
       }else{
           int temp = lenA-lenB;
           while(temp){
               headA=headA->next;
               temp--;
           }
       }
       while(headA&&headB){
           if(headA!=headB){
               headA=headA->next;
               headB=headB->next;
           }else{
               return headA;
           }
       }
       return NULL;
   }
};

例3、链表求环(medium)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:
    方法一:
#include<set>
using namespace std;
/**
 - 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) {
        set<ListNode *> que;
        while(head){
            que.insert(head);
            head=head->next;
            if(que.find(head)!=que.end()){
                return head;
            }
        }
        return NULL;
        
    }
};

方法二:

/**
 - 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) {
        ListNode *slow = head;
        ListNode *fast = head;
        ListNode *meet = NULL;
        while(fast){
            fast = fast->next;
            slow = slow->next;
            if(fast){
                fast = fast->next;
            }
            if(fast==slow){
                meet = fast;
                break;
            }
        }
        if(fast==NULL){
            return NULL;
        }
        while(head&&meet){
            if(head==meet){
                return head;
            }
            head=head->next;
            meet=meet->next;
        }
        return NULL;

    }
};

例4、链表划分(medium)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    思路二:利用两个队列,把小于x的入small队列,大于等于x的入big队列,连接两个链表,更新每个节点的值,让其等于small队列和big队列中元素的值,其中small队列先入,big队列后入。
  • 代码实现:
    方法一:
#include<queue>
using namespace std;
/**
 - Definition for singly-linked list.
 - struct ListNode {
 -     int val;
 -     ListNode *next;
 -     ListNode(int x) : val(x), next(NULL) {}
 - };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        //创建一个小于x的链表头和大于等于x的链表头
        ListNode small(0);
        ListNode big(0);
        ListNode *small_head_move = &small;
        ListNode *big_head_move = &big;
        ListNode *small_head = &small;
        ListNode *big_head = &big;
        while(head){
            ListNode* q = head->next;
            if(head->val<x){
                small_head_move->next = head; 
                small_head_move =head;
            }else{
                big_head_move->next = head;
                big_head_move = head;
            }
            head = q;
        }

             // 让big和small最后指向都为空
            big_head_move->next = NULL;
            big_head = big_head->next;
            // 连接small和big
            small_head_move->next = big_head;
            // 移到头节点的下一个节点
            small_head = small_head->next;
            return small_head;
        
    }
};

方法二:

#include<queue>
using namespace std;
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        queue<int> small_que;
        queue<int> big_que;
        ListNode* start=head;
        ListNode* result=head;
        while(head){
            if(head->val<x){
                small_que.push(head->val);
            }else{
                big_que.push(head->val);
            }
            head = head->next;
        }
        while(start){
            while(!small_que.empty()){
                if(start==NULL){
                    break;
                }
                int top = small_que.front();
                small_que.pop();
                start->val=top;
                start = start->next;
            }
            while(!big_que.empty()){
                if(start==NULL){
                    break;
                }
                int top = big_que.front();
                big_que.pop();
                start->val=top;
                start = start->next;
            }
        }
        return result;
    }
};

例5、复杂链表的复制(hard)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node() {}

    Node(int _val, Node* _next, Node* _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};
*/
#include<map>
#include<vector>
using namespace std;
class Solution {
public:
    Node* copyRandomList(Node* head) {
        map<Node*,int> loc_id;
        vector<Node*> vec;
        Node *start = head;
        int i = 0;
        while(start){
            vec.push_back(new Node(start->val,NULL,NULL));
            loc_id[start]=i;
            i++;
            start = start->next;
        }
        vec.push_back(0);
        Node *result = head;
         i = 0;
        while(result){
            vec[i]->next =vec[i+1];
            if(result->random){
                int id = loc_id[result->random];
                vec[i]->random = vec[id];   
            }
            result=result->next;
            i++;
        }
        return vec[0];
    }
};

例6-a、2个排序链表归并(easy)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
  • 代码实现:
/**
 - Definition for singly-linked list.
 - struct ListNode {
 -     int val;
 -     ListNode *next;
 -     ListNode(int x) : val(x), next(NULL) {}
 - };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode start(0);
        ListNode *new_head = &start;
        ListNode *result = &start;
        while(l1&&l2){
            if(l1->val<=l2->val){
                new_head->next = l1;
                new_head=l1;
                l1=l1->next;
            }else{
                new_head->next = l2;
                new_head=l2;
                l2=l2->next;
            }
        }
        if(l1==NULL){
            new_head->next = l2;
        }
        if(l2==NULL){
            new_head->next = l1;
        }
        return result->next;
    }
};

例6-b、k个排序链表归并(hard)

  • 题目描述:
    在这里插入图片描述
  • 解题思路:
    在这里插入图片描述
    在这里插入图片描述
  • 代码实现:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
#include<vector>
#include<algorithm>

bool cmp(const ListNode *a,const ListNode *b){
    return a->val < b->val;
}

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        vector<ListNode *> vec;
        for( int i = 0;i<lists.size();i++){
            while(lists[i]){
                vec.push_back(lists[i]);
                lists[i]=lists[i]->next;
            }
        }
        if(vec.size()==0){
            return NULL;
        }
        sort(vec.begin(),vec.end(),cmp);
        for(int i = 1;i<vec.size();i++){
            vec[i-1]->next = vec[i];
        }
        vec[vec.size()-1]->next=NULL;
        return vec[0];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值