文章目录
- lc 41 ~ 50
- [41. 缺失的第一个正数](https://leetcode-cn.com/problems/first-missing-positive)
- [42. 接雨水](https://leetcode-cn.com/problems/trapping-rain-water)
- [43. 字符串相乘](https://leetcode-cn.com/problems/multiply-strings)
- [44. 通配符匹配](https://leetcode-cn.com/problems/wildcard-matching)
- [45. 跳跃游戏 II](https://leetcode-cn.com/problems/jump-game-ii)
- [46. 全排列](https://leetcode-cn.com/problems/permutations)
- [47. 全排列 II](https://leetcode-cn.com/problems/permutations-ii)
- [48. 旋转图像](https://leetcode-cn.com/problems/rotate-image)
- [49. 字母异位词分组](https://leetcode-cn.com/problems/group-anagrams)
- [50. Pow(x, n)](https://leetcode-cn.com/problems/powx-n)
lc 41 ~ 50
41. 缺失的第一个正数
原地哈希
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
//原地哈希,映射 nums[i] = i + 1
int n = nums.size();
for(int i = 0; i < n; i++)
while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1]){
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
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) {
stack<int> stk;//单调递减栈,放索引
int res = 0, len = height.size();
for(int i = 0; i < len; i++){
int last = 0;
while(stk.size() && height[stk.top()] <= height[i]){
res += (height[stk.top()] - last) * (i - stk.top() - 1);
last = height[stk.top()];
stk.pop();
}
if(stk.size()) res += (i - stk.top() - 1) * (height[i] - last);
stk.push(i);
}
return res;
}
};
43. 字符串相乘
高精度乘法
class Solution {
public:
string multiply(string num1, string num2) {
if(num1 == "0" || num2 == "0") return "0";
int len1 = num1.length(), len2 = num2.length();
vector<int> a, b;
vector<int> c(len1 + len2);
string ans;
for(int i = num1.length() - 1; i >= 0; i--) a.push_back(num1[i] - '0');
for(int i = num2.length() - 1; i >= 0; i--) b.push_back(num2[i] - '0');
for(int i = 0; i < num1.length(); i++)
for(int j = 0; j < num2.length(); j++)
c[i + j] += a[i] * b[j];
//开始搞进位
int t = 0;//乘积最多len1 + len2 - 1位,所以最后不用管t到最后会不会是非零,一定是0
for(int i = 0; i < len1 + len2; i++){
t += c[i];
c[i] = t % 10;
t /= 10;
}
//开始去零
int k = c.size() - 1;
//为什么不是>=0,因为如果结果是0的话就要保留一位0
while(k > 0 && !c[k]) k--;
for(int j = k; j >= 0; j--) ans += c[j] + '0';
return ans;
}
};
44. 通配符匹配
DP,自己写的,虽然找了很久bug
class Solution {
public:
bool isMatch(string s, string p) {
s = ' ' + s, p = ' ' + p;
int n = s.size(), m = p.size();
vector<vector<bool>> dp(n, vector<bool>(m));
//dp[i][j]:s前i与p前j匹配是否成功
dp[0][0] = true;//都空时当然true
//s不空p空必false;s空p不空,只要都是*就true
int k = 1;
while(k < m && p[k] == '*') dp[0][k++] = true;
for(int i = 1; i < n; i++)
for(int j = 1; j < m; j++){
//p[j]三种情况,字母,?, *
if(p[j] != '?' && p[j] != '*')
dp[i][j] = dp[i - 1][j - 1] && (p[j] == s[i]);
else if(p[j] == '?'){
dp[i][j] = dp[i - 1][j - 1];
}
else{
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
}
}
return dp[n - 1][m - 1];
}
};
y总版,码风很值得学习
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size();
s = ' ' + s, p = ' ' + p;
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1));
dp[0][0] = true;
for(int i = 0; i <= n; i++)
for(int j = 1; j <= m; j++){
if(p[j] == '*')
dp[i][j] = dp[i][j - 1] || i && dp[i - 1][j];//运算优先级先与再或
else
dp[i][j] = (p[j] == s[i] || p[j] == '?') && i && dp[i - 1][j - 1];
}
return dp[n][m];
}
};
45. 跳跃游戏 II
贪心,正向查找可到达的最大位置
class Solution {
public:
int jump(vector<int>& nums) {
int end = 0, maxPos = 0, step = 0, len = nums.size();
for(int i = 0; i < len - 1; i++){
maxPos = max(maxPos, i + nums[i]);//更新所能到达的最远距离
//如果到达边界就更新边界,步数加1
if(i == end){
end = maxPos;
step++;
}
}
return step;
}
};
DP
class Solution {
public:
int jump(vector<int>& nums) {
int len = nums.size();
vector<int> dp(len);//dp[i]表示从0到i的最小步数,dp[0]=0
//[2,3,1,1,4]:则可以发现dp : 0 1 1 2 2可以发现dp是分段递增的
//则可以把j表示为需要走1步可以到i的位置,即为上一层,则状态转移dp[i]=d[j]+1
for(int i = 1, j = 0; i < len; i++){
//寻找一个可以到达i位置的j
while(j + nums[j] < i) j++; //题中满足一定可以到终点,j一定不会越界
dp[i] = dp[j] + 1;
}
return dp[len - 1];
}
};
46. 全排列
简单DFS
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;//因为path长度是确定的,所以建议像y总那样初始化先定好空间
bool st[10];//存放每个是否选过了
vector<vector<int>> permute(vector<int>& nums) {
//path = vector<int>(nums.size());//这样path就不用反复push,pop了,直接修改就行
dfs(nums, 0);
return ans;
}
void dfs(vector<int>& nums, int u){
if(u == nums.size()){
ans.push_back(path);
}
for(int i = 0; i < nums.size(); i++){
if(!st[i]){
st[i] = true;
//path[u] = nums[i];
path.push_back(nums[i]);
dfs(nums, u + 1);
st[i] = false;
path.pop_back();
}
}
}
};
47. 全排列 II
DFS + set去重(效率低)
class Solution {
public:
vector<vector<int>> ans;
set<vector<int>> s;//去重
bool st[10];
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<int> path(nums.size());
dfs(nums, 0, path);
return ans;
}
void dfs(vector<int>& nums, int u, vector<int>& path){
if(u == nums.size()){
if(s.find(path) == s.end()){
ans.push_back(path);
s.insert(path);
}
return;
}
for(int i = 0; i < nums.size(); i++){
if(!st[i]){
st[i] = true;
path[u] = nums[i];
// path.push_back(nums[i]);
dfs(nums, u + 1, path);
st[i] = false;
// path.pop_back();
}
}
}
};
巧妙的去重方法,排序
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
vector<bool> st;
vector<vector<int>> permuteUnique(vector<int>& nums) {
//先排序,将相等的数放一起
sort(nums.begin(), nums.end());
path = vector<int>(nums.size());
st = vector<bool>(nums.size());
dfs(nums, 0);
return ans;
}
void dfs(vector<int>& nums, int u){
if(u == nums.size()){
ans.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i++){
if(!st[i]){
//去重,将相等的元素按优先级分好,前面的没用,这个就不能用,这样就不紊乱
if(i && nums[i - 1] == nums[i] && !st[i - 1]) continue;
st[i] = true;
path[u] = nums[i];
dfs(nums, u + 1);
st[i] = false;
}
}
}
};
48. 旋转图像
脑筋急转弯
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
//方法:先沿副对角线翻转,再沿中轴翻转
//证明正确性,方阵是一圈一圈的正方形组成,不妨验证正方形的正确性就行了
//以一条边为参考,比如下边,沿对角线反转后,变为右边,而顺时针90度在左边,所以再沿中轴翻转即可
//想一下,边上数的顺序也是对的,所以这个方法是对的
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 l = 0, r = n - 1; l < r; l++, r--)
swap(matrix[i][l], matrix[i][r]);
}
};
49. 字母异位词分组
哈希表
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> hash;
vector<vector<string>> ans;
for(auto& s : strs){
string temp = s;
sort(temp.begin(), temp.end());//排完序后满足条件的就一样了
hash[temp].push_back(s);
}
for(auto& item : hash) ans.push_back(item.second);
return ans;
}
};
50. Pow(x, n)
快速幂
class Solution {
public:
double myPow(double x, int n) {
typedef long long LL;
bool is_minus = false;
double ans = 1;
if(n < 0) is_minus = true;
//为什么用LL,-2147483648取绝对值会溢出int
for(LL k = abs((LL)n); k; k >>= 1){
if(k & 1) ans *= x;
x *= x;
}
if(is_minus) ans = 1 / ans;
return ans;
}
};