301. 删除无效的括号
分析
从前往后扫描, 遇到(
就让左括号数量++; 如果遇到)
, 让右括号数量++
l, r表示多余的左右括号数量
code
class Solution {
public:
vector<string> ans;
vector<string> removeInvalidParentheses(string s) {
int l = 0, r = 0;
for (auto x : s)
if (x == '(') l ++ ;
else if (x == ')') {
if (l == 0) r ++ ;
else l -- ;
}
dfs(s, 0, "", 0, l, r); // cnt表示左括号-右括号数量
return ans;
}
void dfs(string& s, int u, string path, int cnt, int l, int r) {
if (u == s.size()) {
if (!cnt) ans.push_back(path);
return ;
}
if (s[u] != '(' && s[u] != ')') dfs(s, u + 1, path + s[u], cnt, l, r);
else if (s[u] == '(') {
int k = u;
while (k < s.size() && s[k] == '(') k ++;
l -= k - u;
for (int i = k - u; i >= 0; i -- ) {
if (l >= 0) dfs(s, k, path, cnt, l, r);
path += '(';
l ++, cnt ++;
}
}else if (s[u] == ')') {
int k = u;
while (k < s.size() && s[k] == ')') k ++ ;
r -= k - u;
for (int i = k - u; i >= 0; i -- ) {
if (cnt >= 0 && r >= 0) dfs(s, k, path, cnt, l, r); // 因为要保证任意前缀中 左括号数量 >= 右括号数量, 所以cnt >= 0
path += ')';
r ++, cnt --;
}
}
}
};
303. 区域和检索 - 数组不可变
分析
前缀和
code
class NumArray {
public:
vector<int> s;
NumArray(vector<int>& nums) {
s.resize(nums.size() + 1);
for (int i = 1; i <= nums.size(); i ++ ) s[i] = s[i - 1] + nums[i - 1];
}
int sumRange(int i, int j) {
++i, ++j;
return s[j] - s[i - 1];
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(left,right);
*/
304. 二维区域和检索 - 矩阵不可变
分析
二位数组前缀和
注意s
要初始化
code
class NumMatrix {
public:
vector<vector<int>> s;
NumMatrix(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return ;
s = vector<vector<int>> (matrix.size() + 1, vector<int>(matrix[0].size() + 1));
for (int i = 1; i <= matrix.size(); i ++ )
for (int j = 1; j <= matrix[0].size(); j ++ )
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + matrix[i - 1][j - 1];
}
int sumRegion(int x1, int y1, int x2, int y2) {
++x1, ++y1, ++x2, ++y2;
return s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
}
};
/**
* Your NumMatrix object will be instantiated and called as such:
* NumMatrix* obj = new NumMatrix(matrix);
* int param_1 = obj->sumRegion(row1,col1,row2,col2);
*/
306. 累加数
分析
高精度
第1个串长度是n, 第2个串长度是n, 判断整个串需要O(n)扫描,
所以O(n^3)
code
class Solution {
public:
string add(string x, string y) {
vector<int> A, B, C;
for (int i = x.size() - 1; i >= 0; i -- ) A.push_back(x[i] - '0');
for (int i = y.size() - 1; i >= 0; i -- ) B.push_back(y[i] - '0');
for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i ++ ) {
if (i < A.size()) t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
string z;
for (int i = C.size() - 1; i >= 0; i -- ) z += to_string(C[i]);
return z;
}
bool isAdditiveNumber(string num) {
for (int i = 0; i < num.size(); i ++ )
for (int j = i + 1; j + 1 < num.size(); j ++ ) {
int a = -1, b = i, c = j;
while (true) {
if (b - a > 1 && num[a + 1] == '0' || c - b > 1 && num[b + 1] == '0') break; // 排除前导0
auto x = num.substr(a + 1, b - a), y = num.substr(b + 1, c - b);
auto z = add(x, y);
if (num.substr(c + 1, z.size()) != z) break; // 下一个数不匹配
a = b, b = c, c += z.size();
if (c + 1 == num.size()) return true;
}
}
return false;
}
};
308.
需要树状数组 + 线段树知识(略过)
309. 最佳买卖股票时机含冷冻期
分析
代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) return 0;
int n = prices.size(), INF = 1e8;
vector<vector<int>> f(n, vector<int>(3, -INF));
f[0][1] = -prices[0], f[0][0] = 0;
for (int i = 1; i < n; i ++ ) {
f[i][0] = max(f[i - 1][0], f[i - 1][2]);
f[i][1] = max(f[i - 1][1], f[i - 1][0] - prices[i]);
f[i][2] = f[i - 1][1] + prices[i];
}
return max(f[n - 1][0], max(f[n - 1][1], f[n - 1][2]));
}
};
310. 最小高度树
分析
两次dfs
code
class Solution {
public:
vector<vector<int>> g;
vector<int> d1, d2, p1, up;
void dfs1(int u, int father) {
for (int x : g[u]) {
if (x == father) continue;
dfs1(x, u);
int d = d1[x] + 1;
if (d >= d1[u]) {
d2[u] = d1[u], d1[u] = d;
p1[u] = x;
}else if (d > d2[u])
d2[u] = d;
}
}
void dfs2(int u, int father) {
for (int x : g[u]) {
if (x == father) continue;
if (p1[u] == x) up[x] = max(up[u], d2[u]) + 1;
else up[x] = max(up[u], d1[u]) + 1;
dfs2(x, u);
}
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
g.resize(n);
d1 = d2 = p1 = up = vector<int>(n);
for (auto& e : edges) {
int a = e[0], b = e[1];
g[a].push_back(b), g[b].push_back(a);
}
dfs1(0, -1);
dfs2(0, -1);
int mind = n + 1;
for (int i = 0; i < n; i ++ ) mind = min(mind, max(up[i], d1[i]));
vector<int> res;
for (int i = 0; i < n; i ++ )
if (max(up[i], d1[i]) == mind)
res.push_back(i);
return res;
}
};
312. 戳气球
分析
code
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size();
vector<int> a(n + 2, 1);
for (int i = 1; i <= n; i ++ ) a[i] = nums[i - 1];
vector<vector<int>> f(n + 2, vector<int>(n + 2));
for (int len = 3; len <= n + 2; len ++ )
for (int i = 0; i + len - 1 <= n + 1; i ++ ) {
int j = i + len - 1;
for (int k = i + 1; k < j; k ++ )
f[i][j] = max(f[i][j], f[i][k] + f[k][j] + a[i] * a[j] * a[k]);
}
return f[0][n + 1];
}
};