41、[困难] 缺失的第一个正数
数组 哈希表
哈希表
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for (int& num : nums) {
if (num <= 0) {
num = n + 1;
}
}
for (int i = 0; i < n; i++) {
int num = abs(nums[i]);
if (num <= n) {
nums[num - 1] = -abs(nums[num - 1]);
}
}
for (int i = 0; i < n; i++) {
if (nums[i] > 0) {
return i + 1;
}
}
return n + 1;
}
};
置换
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; i++) {
while (nums[i] > 0 && 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;
}
};
42、[困难] 接雨水
栈 数组 双指针 动态规划
动态规划
class Solution {
public:
int trap(vector<int>& height) {
int n = height.size();
if (n == 0)
return 0;
vector<int> leftMax(n);
leftMax[0] = height[0];
for (int i = 1; i < n; i++) {
leftMax[i] = max(leftMax[i - 1], height[i]);
}
vector<int> rightMax(n);
rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) {
rightMax[i] = max(rightMax[i + 1], height[i]);
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans += min(leftMax[i], rightMax[i]) - height[i];
}
return ans;
}
};
单调栈
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
stack<int> stk;
int n = height.size();
for (int i = 0; i < n; i++) {
while (!stk.empty() && height[i] > height[stk.top()]) {
int top = stk.top();
stk.pop();
if (stk.empty()) break;
int left = stk.top();
int curWidth = i - left - 1;
int curHeight = min(height[left], height[i]) - height[top];
ans += curWidth * curHeight;
}
stk.push(i);
}
return ans;
}
};
双指针
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
int left = 0, right = height.size() - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = max(leftMax, height[left]);
rightMax = max(rightMax, height[right]);
if (height[left] < height[right]) {
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
}
};
43、[中等] 字符串相乘
数学 字符串

class Solution {
public:
string multiply(string num1, string num2) {
// 解法:无进位相乘后相加,然后处理进位
int m = num1.size(), n = num2.size();
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
vector<int> tmp(m + n - 1);
// 1. 无进位相乘后相加
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');
}
}
// 2. 处理进位
int cur = 0, t = 0;
string ret;
while (cur < m + n - 1 || t) {
if (cur < m + n - 1) {
t += tmp[cur++];
}
ret += t % 10 + '0';
t /= 10;
}
// 3. 处理前导零
while (ret.size() > 1 && ret.back() == '0') {
ret.pop_back();
}
reverse(ret.begin(), ret.end());
return ret;
}
};
44、[困难] 通配符匹配
字符串 动态规划

class Solution {
public:
bool isMatch(string s, string p) {
s = " " + s;
p = " " + p;
int m = s.size();
int n = p.size();
vector<vector<bool>> dp(m, vector(n, false));
dp[0][0] = true;
for (int j = 1; j < n; j++) {
if (p[j] == '*') {
dp[0][j] = true;
} else {
break;
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (p[j] == '*') {
dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
} else {
dp[i][j] =
(p[j] == '?' || s[i] == p[j]) && dp[i - 1][j - 1];
}
}
}
return dp[m - 1][n - 1];
}
};
45、[中等] 跳跃游戏 Ⅱ
贪心

class Solution {
public:
int jump(vector<int>& nums) {
int ret = 0;
int start = 0;
int end = 1;
while (end < nums.size()) {
int maxPos = 0;
for (int i = start; i < end; i++) {
// 能跳到最远的距离
maxPos = max(maxPos, i + nums[i]);
}
start = end;
end = maxPos + 1;
ret++;
}
return ret;
}
};
class Solution {
public:
int jump(vector<int>& nums) {
int ret = 0;
int end = 0;
int maxPos = 0;
for (int i = 0; i < nums.size() - 1; i++) {
// 能跳到最远的距离
maxPos = max(maxPos, i + nums[i]);
if (i == end) {
end = maxPos;
ret++;
}
}
return ret;
}
};
46、[中等] 全排列
数组 回溯
class Solution {
private:
vector<vector<int>> ret;
vector<int> path;
bool check[7];
void dfs(vector<int>& nums) {
if (nums.size() == path.size()) {
ret.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if (check[i] == false) {
path.push_back(nums[i]);
check[i] = true;
dfs(nums);
// 回溯 -> 恢复现场
path.pop_back();
check[i] = false;
}
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums);
return ret;
}
};
47、[中等] 全排列 Ⅱ
数组 回溯
class Solution {
private:
vector<int> path;
vector<vector<int>> ret;
bool check[9];
void dfs(vector<int>& nums, int pos) {
if (pos == nums.size()) {
ret.push_back(path);
return;
}
for (int i = 0; i < nums.size(); ++i) {
// 剪枝
if (check[i] == true ||
(i != 0 && nums[i] == nums[i - 1] && check[i - 1] == false)) {
continue;
}
path.push_back(nums[i]);
check[i] = true;
dfs(nums, pos + 1);
path.pop_back();
check[i] = false;
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
dfs(nums, 0);
return ret;
}
};
48、[中等] 旋转图像
数组 数学
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < (n + 1) / 2; ++j) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = tmp;
}
}
}
};
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// 水平翻转
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < n; ++j) {
swap(matrix[i][j], matrix[n - i - 1][j]);
}
}
// 主对角线翻转
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
swap(matrix[i][j], matrix[j][i]);
}
}
}
};
49、[中等] 字母异位词分组
排序 哈希表 字符串
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> hash;
// 1. 把所有的字母异位词分组
for (const auto& s : strs)
{
string tmp = s;
sort(tmp.begin(), tmp.end());
hash[tmp].push_back(s);
}
// 2. 结果提取出来
vector<vector<string>> ret;
for (const auto& [x, y] : hash)
{
ret.push_back(y);
}
return ret;
}
};
50、[中等] Pow(x, n)
递归 数学
class Solution {
public:
double myPow(double x, int n) {
if (n < 0) {
return 1 / pow(x, -(long long)n);
}
return pow(x, n);
}
double pow(double x, long long n) {
if (n == 0) {
return 1.0;
}
double tmp = pow(x, n / 2);
return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;
}
};