LeetCode Hot 100 代码实现

文章目录

1. 两数之和(Easy,哈希)
class Solution {
   
public:
    vector<int> twoSum(vector<int>& nums, int target) {
   
        unordered_map<int, int> ht;
        for (int i = 0; i < nums.size(); i++) {
   
            int diff = target - nums[i];
            if (!ht.count(diff)) ht[nums[i]] = i;
            else return {
   ht[diff], i};
        }
        return {
   };
    }
};
49. 字母异位词分组(Medium,哈希)
class Solution {
   
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
   
        unordered_map<string, vector<string>> ht;
        for (auto& s : strs) {
   
            auto s2 = s;
            sort(s2.begin(), s2.end());
            ht[s2].push_back(s);
        }

        vector<vector<string>> res;
        for (auto& [k, v] : ht) res.push_back(v);
        return res;
    }
};
128. 最长连续序列(Medium,哈希)
class Solution {
   
public:
    int longestConsecutive(vector<int>& nums) {
   
        if (nums.size() == 0) return 0;
        unordered_set<int> ust;
        for (auto x : nums) ust.insert(x);

        int res = 0;
        for (auto x : ust) {
   
            if (!ust.count(x - 1)) {
   
                int y = x;
                while (ust.count(y)) {
   
                    y++; // 这里不能对y进行删除,因为外层循环正在对ust进行遍历
                }
                res = max(res, y - x);
            }
        }
        return res;
    }
};
283. 移动零(Easy,双指针)
class Solution {
   
public:
    void moveZeroes(vector<int>& nums) {
   
        int k = 0;
        for (int i = 0; i < nums.size(); i++) {
   
            if (nums[i] != 0) swap(nums[i], nums[k++]); // 保证指针k的左边一定都是非零数
        }
    }
};
11. 盛最多水的容器(Medium,贪心(用双指针实现))
class Solution {
   
public:
    int maxArea(vector<int>& height) {
   
        int res = 0;
        int lo = 0, hi = height.size() - 1;
        while (lo < hi) {
   
            res = max(res, (hi - lo) * min(height[lo], height[hi]));
            if (height[lo] < height[hi]) lo++;
            else hi--;
        }
        return res;
    }
};
15. 三数之和(Medium,双指针)
class Solution {
   
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
   
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        int n = nums.size();
        for (int i = 0; i < n; i++) {
   
            if (i && nums[i] == nums[i - 1]) continue;
            int lo = i + 1, hi = n - 1;
            while (lo < hi) {
   
                while (lo < hi && lo > i + 1 && nums[lo] == nums[lo - 1]) lo++;
                while (lo < hi && hi < n - 1 && nums[hi] == nums[hi + 1]) hi--;
                if (lo < hi) {
   
                    int sum = nums[i] + nums[lo] + nums[hi];
                    if (sum == 0) {
   
                        res.push_back({
   nums[i], nums[lo], nums[hi]});
                        lo++, hi--;
                    }
                    else if (sum > 0) hi--;
                    else lo++;
                }
            }
        }
        return res;
    }
};
42. 接雨水(Hard,贪心(用双指针实现))
class Solution {
   
public:
    int trap(vector<int>& height) {
   
        int res = 0;
        int leftMaxH = 0, rightMaxH = 0;
        int lo = 0, hi = height.size() - 1;
        while (lo < hi) {
   
            leftMaxH = max(leftMaxH, height[lo]);
            rightMaxH = max(rightMaxH, height[hi]);
            if (leftMaxH < rightMaxH) {
   
                res += leftMaxH - height[lo];
                lo++;
            }
            else {
   
                res += rightMaxH - height[hi];
                hi--;
            }
        }
        return res;
    }
};
3. 无重复字符的最长子串(Medium,滑动窗)
class Solution {
   
public:
    int lengthOfLongestSubstring(string s) {
   
        unordered_map<char, int> wind;
        int res = 0;
        for (int lo = 0, hi = 0; hi < s.size(); hi++) {
   
            wind[s[hi]]++;
            while (wind[s[hi]] > 1) wind[s[lo++]]--;
            res = max(res, hi - lo + 1);
        }
        return res;
    }
};
438. 找到字符串中所有字母异位词(Medium,滑动窗)
class Solution {
   
public:
    vector<int> findAnagrams(string s, string p) {
   
        unordered_map<char, int> ht;
        for (auto c : p) ht[c]++;
        int target = ht.size(); // 一定要在这一步就统计出哈希表的大小,否则在后面的处理过程中,哈希表的大小会发生改变
        
        unordered_map<char, int> wind;
        int validCnt = 0;
        vector<int> res;
        for (int lo = 0, hi = lo; hi < s.size(); hi++) {
   
            wind[s[hi]]++;
            if (wind[s[hi]] == ht[s[hi]]) validCnt++;
            while (wind[s[hi]] > ht[s[hi]]) {
   
                // if (ht.count(s[lo]) && wind[s[lo]] == ht[s[lo]]) validCnt--;
                if (wind[s[lo]] == ht[s[lo]]) validCnt--; // 不用上面if中的特判也可以通过
                wind[s[lo++]]--;
            }
            
            if (validCnt == target) res.push_back(lo);
        }
        return res;
    }
};
560. 和为 K 的子数组(Medium,前缀和 + 哈希表的综合应用)
class Solution {
   
public:
    int subarraySum(vector<int>& nums, int k) {
   
        int n = nums.size();
        vector<int> s(n + 1);
        for (int i = 1; i <= nums.size(); i++)
            s[i] = s[i - 1] + nums[i - 1];
        
        unordered_map<int, int> ht;
        ht[0] = 1;
        int res = 0;
        for (int i = 1; i <= n; i++) {
   
            res += ht[s[i] - k];
            ht[s[i]]++;
        }
        return res;
    }
};
239. 滑动窗口最大值(Hard,单调队列(须用双端队列实现))
class Solution {
   
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
   
        deque<int> dq;
        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
   
            if (!dq.empty() && dq.front() < i - k + 1)
                dq.pop_front();
            while (!dq.empty() && nums[dq.back()] < nums[i])
                dq.pop_back();
            dq.push_back(i);
            if (i + 1 >= k) res.push_back(nums[dq.front()]);
        }
        return res;
    }
};
76. 最小覆盖子串(Hard,滑动窗)
class Solution {
   
public:
    string minWindow(string s, string t) {
   
        unordered_map<char, int> ht;
        for (auto c : t) ht[c]++;
        int target = ht.size();

        unordered_map<char, int> wind;
        
        string res;
        int validCnt = 0;
        for (int lo = 0, hi = 0; hi < s.size(); hi++) {
   
            wind[s[hi]]++;
            if (wind[s[hi]] == ht[s[hi]]) validCnt++;
            while (wind[s[lo]] > ht[s[lo]]) {
    // 因为判断条件是wind[s[lo]] > ht[s[lo]],所以validCnt永远不可能减小
                wind[s[lo]]--; lo++;
            }
            if (validCnt == target) {
   
                if (res.empty() || res.size() > hi - lo + 1)
                    res = s.substr(lo, hi - lo + 1);
            }
        }
        return res;
    }
};
53. 最大子数组和(Medium,模板题:DP:连续子数组的最大和)
class Solution {
   
public:
    int maxSubArray(vector<int>& nums) {
   
        int res = nums[0]; // 记录0~n-1中连续子数组和的最大值
        int cur = nums[0]; // cur表示以nums[i]结尾的连续子数组的最大和
        for (int i = 1; i < nums.size(); i++) {
   
            cur = max(cur + nums[i], nums[i]);
            res = max(res, cur);
        }
        return res;
    }
};
// 状态表示:
//   集合:dp[i]表示所有以nums[i]结尾的连续子数组构成的集合;
//   属性:集合中元素的最大值
// 状态转移(集合划分):
//   按集合中元素个数是否为1,可划分为两大类:
//      第一类:集合中只有一个元素,即nums[i];
//      第二类:集合中元素个数大于1,即dp[i - 1] + nums[i];
//   由此可得状态转移方程:dp[i] = max(dp[i - 1] + nums[i], nums[i]);
56. 合并区间(Medium,模板题:区间合并)
class Solution {
   
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
   
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
   
            return a[0] < b[0];
        });

        vector<vector<int>> res;
        int st = -1, ed = -1;
        for (auto& t : intervals) {
   
            if (ed < t[0]) {
   
                if (st != -1) res.push_back({
   st, ed});
                st = t[0], ed = t[1];
            }
            else ed = max(ed, t[1]);
        }
        if (st != -1) res.push_back({
   st, ed});
        
        return res;
    }
};
189. 轮转数组(Medium,trick:三次翻转 = 轮转)
class Solution {
   
public:
    void rotate(vector<int>& nums, int k) {
   
        k %= nums.size(); // 本题中,输入的k有可能超出数组长度
        reverse(nums.begin(), nums.end() - k);
        reverse(nums.end() - k, nums.end());
        reverse(nums.begin(), nums.end());
    }
};
238. 除自身以外数组的乘积(Medium,前缀积)
class Solution {
   
public:
    vector<int> productExceptSelf(vector<int>& nums) {
   
        int n = nums.size();
        vector<int> res(n, 1);

        /* 处理前缀积 */
        for (int i = 1; i < n; i++) res[i] = res[i - 1] * nums[i - 1];
        
        /* 处理后缀积,同时得到整个res数组 */
        int suffix = 1;
        for (int i = n - 2; i >= 0; i--) {
   
            suffix *= nums[i + 1];
            res[i] *= suffix;
        }
        
        return res;
    }
};
41. 缺失的第一个正数(Hard,同秩映射)
class Solution {
   
public:
    int firstMissingPositive(vector<int>& nums) {
   
        int n = nums.size();
        for (int i = 0; i < n; i++) {
   
            while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i])
                swap(nums[nums[i] - 1], nums[i]);
        }

        for (int i = 0; i < n; i++) 
            if (nums[i] != i + 1) return i + 1;
        
        return n + 1;
    }
};
// nums[i] = i + 1;
// nums[i] - 1 = i;
// nums[nums[i] - 1] = nums[i];
73. 矩阵置零(Medium,trick:利用原矩阵的第一行和第一列来存储状态)
class Solution {
   
public:
    void setZeroes(vector<vector<int>>& matrix) {
   
        int n = matrix.size(), m = matrix[0].size();
        bool firstRowHasZero = false, firstColHasZero = false;
        for (int j = 0; j < m; j++)
            if (matrix[0][j] == 0) firstRowHasZero = true;
        for (int i = 0; i < n; i++)
            if (matrix[i][0] == 0) firstColHasZero = true;
        
        for (int i = 1; i < n; i++) {
   
            for (int j = 1; j < m; j++) {
   
                if (matrix[i][j] == 0) {
   
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        for (int i = 1; i < n; i++) {
   
            for (int j = 1; j < m; j++) {
   
                if (matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
            }
        }

        if (firstRowHasZero)
            for (int j = 0; j < m; j++) matrix[0][j] = 0;
        
        if (firstColHasZero)
            for (int i = 0; i < n; i++) matrix[i][0] = 0;
    }
};
54. 螺旋矩阵(Medium,方向数组的应用)
class Solution {
   
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
   
        vector<int> dx{
   0, 1, 0, -1}, dy{
   1, 0, -1, 0};
        vector<int> res;
        int x = 0, y = -1;
        int n = matrix.size(), m = matrix[0].size();
        int dir = 0;
        vector<vector<bool>> st(n, vector<bool>(m));
        for (int i = 0; i < n * m; i++) {
   
            x += dx[dir], y += dy[dir];
            if (x < 0 || x >= n || y < 0 || y >= m || st[x][y]) {
   
                x -= dx[dir], y -= dy[dir];
                dir = (dir + 1) % 4;
                x += dx[dir], y += dy[dir];
            }
            res.push_back(matrix[x][y]);
            st[x][y] = true;
        }
        return res;
    }
};
48. 旋转图像(Medium,trick:沿反对角线对称 + 沿铅直中轴线对称 = 顺时针旋转 90 度)
class Solution {
   
public:
    void rotate(vector<vector<int>>& matrix) {
   
        // 先沿反对角线对称,再沿铅直中轴线对称
        int n = matrix.size();
        for (int i = 0; i < n; i++) {
   
            for (int j = 0; j < i; j++) {
   
                swap(matrix[i][j], matrix[j][i]);
            }
        }

        for (int i = 0; i < n; i++) {
   
            for (int j = 0; j < n / 2; j++) {
   
                swap(matrix[i][j], matrix[i][n - 1 - j]);
            }
        }
    }
};
240. 搜索二维矩阵 II(Medium,trick:从右上角开始查找,可使时间复杂度降至 O ( max ⁡ ( m , n ) ) O(\max (m, n)) O(max(m,n)))
class Solution {
   
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
   
        int n = matrix.size(), m = matrix[0].size();
        int i = 0, j = m - 1;
        while (i < n && j >= 0) {
   
            if (matrix[i][j] == target) return true;
            else if (matrix[i][j] > target) j--;
            else i++;
        }
        return false;
    }
};
160. 相交链表(Easy,双指针)
/**
 * 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) {
   
        auto p1 = headA, p2 = headB;
        while (p1 != p2) {
   
            p1 = p1 ? p1->next : headB;
            p2 = p2 ? p2->next : headA;
        }
        return p1;
    }
};
206. 反转链表(Easy,模板题:反转链表)
/**
 * 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* reverseList(ListNode* head) {
   
        ListNode* prev = nullptr, *cur = head;
        while (cur) {
   
            auto next = cur->next;
            cur->next = prev;
            prev = cur;
            cur = next;
        }
        return prev;
    }
};
234. 回文链表(Easy(实际上是 Medium),找链表中点 + 反转链表 + 判断回文)
/**
 * 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:
    bool isPalindrome(ListNode* head) {
   
        /* step1: 找到中间靠左节点(如果链表有奇数个节点,则找到的是最中间的节点;
                          如果链表有偶数个节点,则找到的是后半段的前一个位置。) */
        auto fast = head->next, slow = head;
        while (fast && fast->next) {
   
            fast =</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值