力扣面试题46.题解
思路
这道题是动态规划的一道很典型的问题。
从例子12258谈起。
我们可以知道,当分割成1,2,2,5,8时,
1显然只有一种分割;1,2则可以有2种,因为12<=25.
那么在1,2,2,的情况下呢?有3种分割方案。怎么算出来的呢?
我们知道,22<25,所以当后面的22捆绑在一起的时候,实际上就是看1以及1以前的数字,有多少种分割方案。
在我们声明的dp数组里,数组里存放的元素为当前元素下标下,该元素及其前面的元素组成的数字,可以分割的种类个数。
而当2和2不捆绑,分开的时候,实际上就是看前面的这个2以及2以前的数字,有多少种分割方案。
如此一来,dp[i]=dp[i-1]+dp[i-2]的状态转移方程就出来了。
特别注意的是,当遍历到8,发现58>25时,元素8的的dp数组值,实际上就是依赖于1,2,2,5的分割数目,即dp[i]=dp[i-1].
i-2小于0时怎么办?比如1,2.我们可以知道1,2捆绑一起后,就没有元素了,所以dp[i-2]=0,不必加上去(本来也越界了),此时只依赖于dp[i-1]。12<25,自然两者可以捆绑,因此dp[i]=dp[i-1]+1.加上的1,实际上就是可以捆绑的一种分割。
代码
class Solution {
public:
int translateNum(int num) {
if(num==0)return 1;//数字为0 显然只能分割一份
vector<int> a;
while(num>0){
a.push_back(num%10);
num/=10;
}
reverse(a.begin(),a.end());//此时数组a存放的是分割的一个一个数字
vector<int> dp(a.size(),0);//建立dp数组
dp[0]=1;
for(int i=1;i<a.size();i++){
int tmp=a[i-1]*10+a[i];
if(tmp==a[i]){
dp[i]=dp[i-1];//这是一个特殊情况,表明前一个元素是0,比如101这个例子。由报错系统可以看出,1,01这种分割是不被允许的。可能是因为01表示的不是1,而是八进制下的数的原因。因此遇到这种情况时,我们直接跳过1,01这种情况:即01不捆绑在一起了,删去等式的dp[i-2]。
}
else {
if(tmp<=25){
if(i-2>=0){
dp[i]=dp[i-1]+dp[i-2];
}
else {
dp[i]=dp[i-1]+1;
}
}
else {
dp[i]=dp[i-1];
}
}
}
return dp[a.size()-1];//最后的dp值即为全部元素的分割种类数
}
};