125. Valid Palindrome
1 | class Solution { |
T(n): O(n)
S(n): O(1)
review
1 | class Solution { |
1 | class Solution { |
T(n): O(n)
S(n): O(1)
1 | class Solution { |
1 | class Solution { |
T(n): O(n)
S(n): O(1)
IAMSVEG
1 | class Solution { |
不修改原数组的O(n)空间复杂度的解法 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int sz = triangle.size();
vector<int> dp(sz);
dp[0] = triangle[0][0];
for(int i = 1; i < sz; ++i)
{
dp[i] = dp[i - 1] + triangle[i][i]; // 第i行有i+1个元素,所以dp[i]就表示最后一个,这里需要上面一行的前一个元素加上当前元素
for(int j = i - 1; j > 0; --j)
dp[j] = min(dp[j], dp[j - 1]) + triangle[i][j];
dp[0] += triangle[i][0];
}
return *min_element(dp.begin(), dp.end());
}
};1
2
3
4
5
6
7
8
9
10
11class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int level = triangle.size();
vector<int> dp(triangle.back().begin(), triangle.back().end());
for(int i = level - 2; i >= 0; --i)
for(int j = 0; j < i + 1; ++j)
dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j];
return dp[0];
}
};
要选择最优的过去,不要选择不确定的未来
1 | class Solution { |
1 | class Solution { |
抄de
transpose and reflect in linear algebra 1
2
3
4
5
6
7
8
9
10
11
12
13class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for(int i = 0; i < n; ++i)
for(int j = i; j < n; ++j)
swap(matrix[i][j], matrix[j][i]);
for(int i = 0; i < n; ++i)
for(int j = 0; j < n / 2; ++j)
swap(matrix[i][j], matrix[i][n - j - 1]);
}
};
1 | class Solution { |
1 | class Solution { |
将问题分解为每个小小的n会生成多少的树,最后左树数 * 右树数
review 1
2
3
4
5
6
7
8
9
10
11class Solution {
public:
int numTrees(int n) {
vector<int> dp(n + 1);
dp[0] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= i; ++j)
dp[i] += dp[j - 1] * dp[i - j];
return dp.back();
}
};
1 | class Solution { |
T(n) : O(m * n)
S(n) : O(1)
动态规划问题可以归结为网格,此处网格中元素为每个块对路径的贡献度,当本块为障碍时则贡献为0,当本块无障碍,则上方和左方的方块可以走过来,贡献的路径就是上和左相加
1 | class Solution { |
1 | class Solution { |
T(n) : O(m * n)
S(n) : O(m * n)
观察代码,发现每次用到的数据只有dp[i][j], dp[i][j - 1]和dp[i - 1][j],考虑dp[i][j], dp[i][j - 1]合并到一个一维数组,剩下的再生产一个一维数组。
参考unique path中的方法 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
size_t m = grid.size(), n = grid[0].size();
int* cur = new int[n];
int* pre = new int[n];
for (size_t i = 0; i < m; ++i)
{
for (size_t j = 0; j < n; ++j)
{
if (i == 0 && j == 0)
cur[j] = grid[i][j];
else if (i == 0)
cur[j] = cur[j - 1] + grid[i][j];
else if (j == 0)
cur[j] = pre[j] + grid[i][j];
else
cur[j] = min(pre[j], cur[j - 1]) + grid[i][j];
}
swap(cur, pre);
}
return pre[n - 1];
}
};
S(n) : O(2 * n)
pre[j] 与 cur[j] 可以合并
1 | class Solution { |
T(n) : O(m * n)
S(n) : O(n)
1 | class Solution { |
1 | class Solution { |
官解的手写hash函数或者string作为位图,每一位来记录。
1 | class Solution { |
Time Limit Exceeded
1 | class Solution { |
空间优化 1
2
3
4
5
6
7
8
9
10class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> dp(n, 1);
for(int i = 1; i < m; ++i)
for(int j = 1; j < n; ++j)
dp[j] += dp[j - 1];
return dp.back();
}
};
1 | class Solution { |
1 | class Solution { |
review 1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution {
public:
int climbStairs(int n) {
if(n < 2)
return n;
int a = 1, b = 2;
for(int i = 3; i <= n; ++i)
{
a += b;
swap(a, b);
}
return b;
}
};
Whenever you see a question that asks for the maximum or minimum of something, consider Dynamic Programming as a possibility
1 | class Solution { |
1 | class Solution { |
取中点,往左计算和,往右计算和,这时候有三种情况,中点是最长子串之中的元素,最长子串在中点右边,最长子串在中点左边。对于第一种情况,那就是左+右+中,对于后两种,那么再对左右子串进行同样的查找(DQ)