LeetCode热题100(1-7)
目录
一、数组操作篇
1. 移动零(283. Move Zeroes)
2. 盛最多水的容器(11. Container With Most Water)
二、查找与哈希篇
1. 两数之和(1. Two Sum)
2. 字母异位词分组(49. Group Anagrams)
三、数组进阶篇
1. 三数之和(15. 3Sum)
2. 最长连续序列(128. Longest Consecutive Sequence)
四、挑战难题篇:接雨水(42. Trapping Rain Water)
总结
作为一名算法爱好者,LeetCode是我提升编程能力、锻炼逻辑思维的绝佳平台。今天,我想分享几道LeetCode经典题目,聊聊它们的解法思路和C++实现,希望能给正在刷题的你带来一些启发。
一、数组操作篇
1. 移动零(283. Move Zeroes)

问题描述:给定一个数组,将所有0移动到数组末尾,同时保持非零元素的相对顺序,要求原地操作。
解题思路:使用双指针法,一个指针 pre 追踪非零元素的位置,另一个指针 cur 遍历数组。当 cur 遇到非零元素时,与 pre 位置的元素交换,然后 pre 和 cur 都后移;若遇到0,仅 cur 后移。
C++实现:
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++实现:
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++实现:
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++实现:
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++实现:
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++实现:
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++实现:
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;}
};
总结
通过这些题目的练习,我们可以总结出一些常见的算法思维和技巧:
- 双指针法:在数组、字符串问题中应用广泛,如两数之和、三数之和、盛最多水的容器、接雨水等。
- 哈希表:用于快速查找、分组,如字母异位词分组、两数之和的优化解法。
- 排序:帮助我们处理重复、连续等问题,如三数之和、最长连续序列。
- 原地操作:通过指针技巧减少空间复杂度,如移动零。
刷题是一个持续积累的过程,每道题都有其独特的思路和价值。希望这篇博客能帮助大家更好地理解这些经典题目,在算法学习的道路上不断进步!