LeetCode热题100(1-7)

目录

一、数组操作篇

[1. 移动零(283. Move Zeroes) ​](#1. 移动零(283. Move Zeroes))

[2. 盛最多水的容器(11. Container With Most Water) ​](#2. 盛最多水的容器(11. Container With Most Water))

二、查找与哈希篇

[1. 两数之和(1. Two Sum) ​](#1. 两数之和(1. Two Sum))

[2. 字母异位词分组(49. Group Anagrams) ​](#2. 字母异位词分组(49. Group Anagrams))

三、数组进阶篇

[1. 三数之和(15. 3Sum)](#1. 三数之和(15. 3Sum))

[2. 最长连续序列(128. Longest Consecutive Sequence) ​](#2. 最长连续序列(128. Longest Consecutive Sequence))

[四、挑战难题篇:接雨水(42. Trapping Rain Water) ​](#四、挑战难题篇:接雨水(42. Trapping Rain Water))

总结


作为一名算法爱好者,LeetCode是我提升编程能力、锻炼逻辑思维的绝佳平台。今天,我想分享几道LeetCode经典题目,聊聊它们的解法思路和C++实现,希望能给正在刷题的你带来一些启发。

一、数组操作篇

1. 移动零(283. Move Zeroes)

问题描述:给定一个数组,将所有0移动到数组末尾,同时保持非零元素的相对顺序,要求原地操作。

解题思路:使用双指针法,一个指针 pre 追踪非零元素的位置,另一个指针 cur 遍历数组。当 cur 遇到非零元素时,与 pre 位置的元素交换,然后 pre 和 cur 都后移;若遇到0,仅 cur 后移。

C++实现:

cpp 复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int cur = 0, pre = -1;
        while (cur < nums.size()) {
            if (nums[cur] == 0) cur++;
            else {
                swap(nums[++pre], nums[cur++]);
            }
        }
    }
};

2. 盛最多水的容器(11. Container With Most Water)

问题描述:给定n条垂线,找到两条线,使得它们与x轴构成的容器能容纳最多的水。

解题思路:双指针从两端向中间移动。容器的容量由较短的垂线高度和两线间距决定。每次移动较短垂线的指针,因为移动较长垂线的指针不会得到更大的容量。

C++实现:

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int heightSize = height.size(), max_area = 0;
        int left = 0, right = heightSize - 1;
        while (left < right) {
            int area = (right - left) * min(height[left], height[right]);
            if (area > max_area) max_area = area;
            if (height[left] < height[right]) left++;
            else right--;
        }
        return max_area;
    }
};
 

二、查找与哈希篇

1. 两数之和(1. Two Sum)

问题描述:给定数组和目标值,找出和为目标值的两个整数的下标。

解题思路:暴力法是双重循环遍历所有可能的数对,时间复杂度O(n²)。

C++实现:

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int numsSize = nums.size();
        for (int i = 0; i < numsSize; i++)
            for (int j = i + 1; j < numsSize; j++)
                if (nums[i] + nums[j] == target)
                    return {i, j};
        return {};
    }
};
 

注:此解法时间复杂度较高,更优的解法是使用哈希表,时间复杂度可降至O(n)。

2. 字母异位词分组(49. Group Anagrams)

问题描述:将字母异位词(字母组成相同,顺序不同的单词)组合在一起。

解题思路:将每个单词排序,排序后的结果作为哈希表的键,相同键的单词属于同一组字母异位词。

C++实现:

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> hash;
        for (auto s : strs) {
            string tmp = s;
            sort(tmp.begin(), tmp.end());
            hash[tmp].push_back(s);
        }
        vector<vector<string>> ret;
        for (auto& [x, y] : hash)
            ret.push_back(y);
        return ret;
    }
};

三、数组进阶篇

1. 三数之和(15. 3Sum)

问题描述:找出数组中所有和为0的三元组,且不重复。

解题思路:先排序,然后固定一个数,用双指针找另外两个数,同时注意去重(包括固定数的去重和双指针移动时的去重)。

C++实现:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> v;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        if (n < 3)
            return {};
        for (int i = 0; i < n - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1])
                continue;
            int target = -nums[i];
            int left = i + 1, right = n - 1;
            while (left < right) {
                if (nums[left] + nums[right] > target)
                    right--;
                else if (nums[left] + nums[right] < target)
                    left++;
                else {
                    v.push_back({nums[i], nums[left], nums[right]});
                    while (left < right && nums[left] == nums[left + 1])
                        left++;
                    while (left < right && nums[right] == nums[right - 1])
                        right--;
                    left++;
                    right--;
                }
            }
        }
        return v;
    }
};

2. 最长连续序列(128. Longest Consecutive Sequence)

问题描述:给定未排序的整数数组,找出最长连续序列的长度,要求时间复杂度O(n)。

解题思路:先排序,然后遍历数组,统计连续序列的长度,遇到重复元素则跳过。

C++实现:

cpp 复制代码
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if (nums.empty()) return 0;
        sort(nums.begin(), nums.end());
        int len = 0, ret = 0;
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] - nums[i - 1] == 1) len++;
            else if (nums[i] - nums[i - 1] == 0) continue;
            else {
                ret = max(ret, len);
                len = 0;
            }
        }
        ret = max(ret, len);
        return ret + 1;
    }
};

四、挑战难题篇:接雨水(42. Trapping Rain Water)

问题描述:给定n个非负整数表示柱子的高度图,计算下雨后能接多少雨水。

解题思路:双指针法,分别记录左右的最大高度。如果左最大高度小于右最大高度,当前左柱子能接的雨水由左最大高度决定;否则由右最大高度决定。

C++实现:

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        int sz = height.size();
        if (sz < 3) return 0;
        int left = 0, right = sz - 1;
        int leftMax = 0, rightMax = 0;
        int ret = 0;
        while (left < right) {
            leftMax = max(leftMax, height[left]);
            rightMax = max(rightMax, height[right]);
            if (leftMax < rightMax) ret += leftMax - height[left++];
            else ret += rightMax - height[right--];
        }
        return ret;
    }
};
 

总结

通过这些题目的练习,我们可以总结出一些常见的算法思维和技巧:

**- 双指针法:在数组、字符串问题中应用广泛,如两数之和、三数之和、盛最多水的容器、接雨水等。

  • 哈希表:用于快速查找、分组,如字母异位词分组、两数之和的优化解法。
  • 排序:帮助我们处理重复、连续等问题,如三数之和、最长连续序列。
  • 原地操作:通过指针技巧减少空间复杂度,如移动零。**

刷题是一个持续积累的过程,每道题都有其独特的思路和价值。希望这篇博客能帮助大家更好地理解这些经典题目,在算法学习的道路上不断进步!

相关推荐
新学笺3 小时前
数据结构与算法 —— Java单链表从“0”到“1”
算法
同元软控3 小时前
首批CCF教学案例大赛资源上线:涵盖控制仿真、算法与机器人等9大方向
算法·机器人·工业软件·mworks
yiqiqukanhaiba4 小时前
Linux编程笔记2-控制&数组&指针&函数&动态内存&构造类型&Makefile
数据结构·算法·排序算法
PKNLP4 小时前
逻辑回归(Logistic Regression)
算法·机器学习·逻辑回归
可触的未来,发芽的智生4 小时前
新奇特:神经网络的自洁之道,学会出淤泥而不染
人工智能·python·神经网络·算法·架构
放羊郎4 小时前
SLAM算法分类对比
人工智能·算法·分类·数据挖掘·slam·视觉·激光
Juan_20125 小时前
P1447题解
c++·数学·算法·题解
ai智能获客_狐狐5 小时前
智能外呼产品架构组成
人工智能·算法·自然语言处理·架构·语音识别
Algo-hx6 小时前
数据结构入门 (五):约束即是力量 —— 深入理解栈
数据结构·算法