给你一个字符串 s,找到 s 中最长的回文子串。
class Solution {
public:
string longestPalindrome(string s) {
if(s.empty())
return "";
int length = s.size();
if(length == 1)
return s;
vector<vector<bool>> dp(length, vector<bool>(length, false));
string result = "";
for(int i = length - 1; i >= 0; i--)
for(int j = i; j < length; j++){
if(j == i)
dp[i][j] = true;
else if(i + 1 == j && s[i] == s[j])
dp[i][j] = true;
else
dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1];
if(dp[i][j] == true && j - i + 1 >= result.size())
result = s.substr(i, j - i + 1);
}
return result;
}
};
经验:
1、问题拆分为两个部分,一部分是如何确定这个子字符串是回文,另一个问题是考虑长度。拆分开来西靠比较容易解决,并且由于回文字符串的性质可知,同时考虑两边添加元素远比一边添加元素要来的容易。
2、注意:本题DP解法中,遍历顺序是十分考究的,只有解法中的一边++一边–才能够按照要求的顺序更新。
3、C++中二维数组的创建十分容易,
vector<vector> dp(m, vector(n, a))表示的是初始化一个m行n列的,初始值为a的二维数组。
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
for(int i = 0; i < m; i++)
dp[i][0] = 1;
for(int j = 0; j < n; j++)
dp[0][j] = 1;
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m - 1][n - 1];
}
};
一遍过,水题。
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
if(obstacleGrid.empty() || obstacleGrid[0].empty())
return 0;
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<long>>dp(m, vector<long>(n, 0));
for(int i = 0; i < m; i++)
if(obstacleGrid[i][0] == 1)
break;
else
dp[i][0] = 1;
for(int j = 0; j < n; j++)
if(obstacleGrid[0][j] == 1)
break;
else
dp[0][j] = 1;
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
if(obstacleGrid[i][j] == 1)
dp[i][j] = 0;
else
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m - 1][n - 1];
}
};
升级版,依旧是水题,不过二维数组的下标位置需要注意。。写反了开始一直没检查出来。。
2、heap-buffer-overflow在LeetCode中一般是由数组下标越界造成的。
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
if(grid.empty() || grid[0].empty())
return 0;
int m = grid.size(), n = grid[0].size();
vector<vector<int>>dp(m, vector<int>(n, 0));
for(int i = 0; i < m; i++)
if(i == 0)
dp[i][0] = grid[0][0];
else
dp[i][0] = dp[i - 1][0] + grid[i][0];
for(int j = 0; j < n; j++)
if(j == 0)
;
else
dp[0][j] = dp[0][j - 1] + grid[0][j];
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
return dp[m - 1][n - 1];
}
};
水题,一遍过