LeetCode 力扣 刷题记录 热题 HOT 100(141,142,146,148,152)题目+算法分析+Cpp解答

GitHub链接:https://github.com/WilliamWuLH/LeetCode

如果你觉得不错可以 ⭐Star 和 Fork ❤

141.Linked List Cycle

方法一:

/**
 * 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) {
        while(head != NULL){
            if(head->val == -50505050)
                return true;
            else
                head->val = -50505050;
            head = head->next;
        }
        return false;
    }
};

方法二:

/**
 * 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) {
        vector hash;
        while(head != NULL){
            if(find(hash.begin(), hash.end(), head) != hash.end())
                return true;
            else
                hash.push_back(head);
            head = head->next;
        }
        return false;
    }
};

142.Linked List Cycle II

方法一:保存链表结点

/**
 * 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) {
        vector hash;
        while(head != NULL){
            if(find(hash.begin(), hash.end(), head) != hash.end())
                return head;
            else
                hash.push_back(head);
            head = head->next;
        }
        return NULL;
    }
};

方法二:Floyd 算法 + 双指针(快慢指针)

​ 慢指针一次走一步,快指针一次走两步。

​ 首先需要判断快指针会不会走到链表的结尾,即会不会遇到 NULL,以此判断链表是否有环。

​ 如果快指针和慢指针相遇了,则说明链表有环,接下来就是数学推导了:

​ 假设链表中不成环(链)的长度为 L,环的长度为 C,在第一次相遇时慢指针走的长度为 S,快指针走的长度为 F。假设其中慢指针在环中走的长度为 Cs,快指针在环中走的长度为 Cf。可以得出以下结论:

  • F = 2 S F = L + Cf S = L + Cs Cf = C + Cs

  • 2 ( L + Cs ) = L + Cf L + 2 Cs = Cf L + 2 Cs = C + Cs

  • L = C - Cs

    所以,慢指针走完剩下的环的长度等于从链表开头走到环的起点的长度,由此可以得到环的开始结点。

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

146.LRU Cache

map存数据,vector更新优先级:

class LRUCache {
private:
    map store;
    int size = 0;
    vector LRU;
public:
    LRUCache(int capacity) {
        size = capacity;
    }
    
    int get(int key) {
        if(store.count(key) > 0){
            vector::iterator it = find(LRU.begin(), LRU.end(), key);
            LRU.erase(it);
            LRU.push_back(key);
            return store[key];
        }
        else
            return -1;
    }
    
    void put(int key, int value) {
        if(store.count(key) > 0){
            vector::iterator it = find(LRU.begin(), LRU.end(), key);
            LRU.erase(it);
            LRU.push_back(key);
            store[key] = value;
        }
        else if(size > 0){
            store[key] = value;
            LRU.push_back(key);
            size--;
        }
        else{
            int tkey = *(LRU.begin());
            store.erase(tkey);
            LRU.erase(LRU.begin());
            store[key] = value;
            LRU.push_back(key);
        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

148.Sort List

归并排序 + 快慢指针:

​ 快慢指针:找出链表的中间位置。

​ 归并排序:将两个链表按顺序进行合并。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head == NULL || head->next == NULL)
            return head;
        ListNode* mid;
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast != NULL && fast->next!= NULL){
            mid = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        mid->next = NULL;
        return merge(sortList(head), sortList(slow));
    }
    ListNode* merge(ListNode* l1, ListNode* l2){
        ListNode head;
        ListNode* ans = &head;
        while(l1 != NULL && l2 != NULL){
            if(l1->val < l2->val){
                ans->next = l1;
                l1 = l1->next;
            }
            else{
                ans->next = l2;
                l2 = l2->next;
            }
            ans = ans->next;
        }
        ans->next = l1 == NULL ? l2 : l1;
        return head.next;
    }
};

152.Maximum Product Subarray

动态规划:

​ 由于是乘法运算,所以最大的数可能是通过负数乘以负数,也可能是正数乘以正数。

​ 所以在讨论到数组中的某一个数时需要维护一个以该数结尾的子数组的最大值和最小值(可能为负数)。

​ 讨论到每一个数时需要时刻更新此时的答案(最大值)。

class Solution {
public:
    int maxProduct(vector& nums) {
        int tmax = 1,tmin = 1;
        int ans = INT_MIN;
        int len = nums.size();
        for(int i=0; i

你可能感兴趣的:(算法,LeetCode,C++)