动态规划算法
1、目标
是求解决策过程最优化的过程。
2、方法
把原问题分解成子问题进行求解,也就是分治的思想。
3、过程
主要分四步:
- 划分子问题:把一个大问题分解为小问题
- 状态表示:如何处理小问题。
- 状态转移:也就是父问题如何推导出子问题。
- 确定边界:确定初始状态是什么?最小的子问题?最终状态又是什么。
4、例题
(1)力扣:5. 最长回文子串
class Solution {
public:
string longestPalindrome(string s) {
int length = s.length();
vector<vector<bool>> answer(length, vector<bool>(length));
int Start = 0,End = 0;
//自己与自己的关系全部设为true,也就是只有一个的情况
for(int i = 0;i < length;i++){
answer[i][i] = true;
}
//开始进行遍历,达到条件的就改成true
for(int j = 1;j < length;j++){
for(int i = 0;i < j;i++){
if(s.at(i) == s.at(j) &&(i+1 == j || answer[i+1][j-1]))
{
if(j - i >= End - Start){
Start = i;
End = j;
}
answer[i][j] = true;
}
}
}
return s.substr(Start,(End - Start + 1));
}
};
ps:我在刷这一部分题的时候遇见的问题很大,做起来很困难,唉。
(1)力扣:1018. 可被 5 整除的二进制前缀
打个比方[0,1,1,1],第一个数是0,第二个数是01,第三个是011,第四个是0111,化为十进制,分别为0,1,3,7.然后根据二进制规则,数据每向左移动一位,数据大小乘2.
那么可以用sum = 0, sum = sum *2 + num。num就是[0,1,1,1]里的元素,sum就是化成的十进制。
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& A) {
vector<bool> a;
int sum = 0;
for(auto num : A){
sum = sum * 2 +num;
cout<<sum % 5<<endl;
if(sum % 5 == 0) a.push_back(1);
else if(sum % 5 != 0 ) a.push_back(0);
}
return a;
}
};
然后运行超时了所以我准备改造一下
首先sum*2我们可以改造成sum<<1,直接改成二进制移动位置,然后可以让sum等于之前sum留下的余数
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& A) {
vector<bool> a;
int sum = 0;
for(auto num : A){
sum = (sum << 1) +num;
a.push_back(sum % 5 == 0);
}
return a;
}
};
然后又报错int类型的数据的存储空间不够,那就想办法让int存的小一点.
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& A) {
vector<bool> a;
int sum = 0;
for(auto num : A){
sum = ((sum << 1) +num) %5;
a.push_back(sum == 0);
}
return a;
}
};
每次sum都除一下5让sum只等于他的余数,因为多余的数怎么也是五的倍数,关键就是看余出来的这一部分数据能够怎么处理。