LeetCode算法入门(第六十二天)
动归
5.最长回文子串
首先确定dp[i][j]数组的含义:表示s[i…j]是否为回文子串;
初始化dp数组,一个字符是回文子串,同时初始化回文子串的最大长度为1
状态转移公式:当s[i]==s[j]时,s[i…j]是否为回文子串由s[i+1…j-1]是否为回文子串决定,所以dp[i][j]=dp[i+1][j-1]决定
外层循环控制参与判断回文子串的字符串长度,内层循环判断具体区间内的字符串是否为回文子串
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if(n < 2){
return s;
}
int maxLen = 1; //一个字符是回文子串
int begin = 0;
//dp[i][j] 表示s[i...j]是否为回文子串
vector<vector<int>> dp(n, vector<int>(n));
for(int i = 0; i < n; i++){
dp[i][i] = true; //一个字符是回文子串
}
for(int L = 2; L <= n; L++){
for(int i = 0; i < n; i++){
// 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
int j = L + i -1;
if(j >= n){
break;
}
if(s[i] != s[j]){
dp[i][j] = false;
}else{
if(j - i < 3){ //0,1,2个字符子串都是回文子串
dp[i][j] = true;
}else{
dp[i][j] = dp[i+1][j-1]; //s[i...j]是否为回文子串由s[i+1...j-1]是否为回文子串决定
}
}
//只要 dp[i][L] == true 成立,就表示子串 s[i...L] 是回文,此时记录回文长度和起始位置
if(dp[i][j] && j - i + 1 > maxLen){
maxLen = j - i +1;
begin = i;
}
}
}
return s.substr(begin, maxLen);
}
};
413.等差数列划分
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
vector<int> dp(nums.size(), 0); //dp[i] nums数组中的第i+1个数组成的等差数列的个数
int result = 0;
for(int i = 2; i < nums.size(); i++){
if(nums[i] - nums[i-1] == nums[i-1] - nums[i-2]){ //当符合等差条件时,才递推
dp[i] = dp[i-1] + 1; //比i-1时,多了一个本身
result += dp[i]; //结果为符合条件的dp数组的值的和
}
}
return result;
}
};
91.解码方法
class Solution {
public:
int numDecodings(string s) {
vector<int> dp(s.length() + 1, 0); //dp[i]表示s[1...i]个字符的解码情况
dp[0] = 1; //题目给的是非空字符串,但为了状态转移 初始化dp[0]为1
for(int i = 1; i <= s.length(); i++){
if(s[i-1] != '0'){ //使用一个字符,对s[i]进行解码
dp[i] = dp[i-1];
}
if(i > 1 && s[i-2] != '0' && (10*(s[i-2] - '0') + (s[i-1] - '0') <= 26)){ //使用两个字符,即s[i-1]s[i]进行解码
dp[i] += dp[i-2]; //需要加上使用一个字符时dp[i]的值
}
}
return dp[s.length()];
}
};
139.单词拆分
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> uset(wordDict.begin(), wordDict.end()); //用于判断字典中是否存在
vector<bool> dp(s.size()+ 1, false); //dp[i],字符串长度为i时,是否可拆分为一个或多个字典中出现的单词
dp[0] = true; //尽管实际上dp[0]表示字符串为空,题目说了字符串不为空,但是dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递归的根基,dp[0]一定要为true,否则递归下去后面都都是false了
for(int i = 1; i <= s.size(); i++){
for(int j = 0; j < i; j++){
string word = s.substr(j, i-j);
if(uset.find(word) != uset.end() && dp[j]){ //如果dp[j]为true,且[j,i]这个区间的子串出现在字典中,那么dp[i]为true
dp[i] = true;
}
}
}
return dp[s.size()];
}
};