1.题目
2.思路
DFS--( 2^31)
看见这题,我第一反义是递归,每次都有选择这个数字和不选这个数字的权利。数据范围是2^31次方,也就是最多有31个数字。每次都有两个操作判断,时间复杂度也是2^31 > 10 ^ 8.感觉会超时!但是由于中间存在剪枝操作,每次只有10-25之间的数字才有两种组合方式,所以大部分数字组合都会被剪掉。试着写了一下,11ms, 超过6%。
class Solution {
Set<String>set = new HashSet();
String s = "";
public int translateNum(int num) {
s = num + "";
int n = s.length();
// System.out.println(Math.pow(2, 31));
dfs("", 0, n);
return set.size();
}
public void dfs(String temp, int index, int n){
if(index == n){
set.add(temp);
return ;
}
// 不选这个数
if(index + 1 < n ){
if((s.charAt(index) == '1' ) || (s.charAt(index) == '2' && s.charAt(index + 1) <= '5')){
temp += (s.substring(index, index + 2) + 'a' );
dfs(temp, index + 2, n);
}
}
temp += (s.charAt(index) + 'a');
dfs(temp, index + 1, n);
}
}
动态规划--O(N)
查看题解,发现是动态规划,一开始思路根本没往这个方向靠。其实仔细一想,这种求组合数个数的用动态规划非常合适了!
动态规划三部曲-定义-初始化-状态转移
1.定义:一般题目求啥就可以尝试定义成啥。这里dp[i]就定义为前i个数能组成的最大方案数。
2.初始化:假如n = 0, 那么可以转化为’a',只有一种可能。那么dp[1] = 1。一开始dp[0] 我也是定义的0,然后发现计算dp[2]的时候就不对了。这里也需要把dp[0] = 1.
3.状态转移:重中之重。分成两种情况讨论;
第一种情况:第i个数只能自己组队,不能和前面的数一起配对,那么dp[i] = dp[i -1].
第二种情况:第i个数可以和前一个数组队,也就是像10 -25之间这种。假如是这两个数组在一起,那么dp[i] = dp[i - 2]. 当然这里肯定也可以两个都分开独自组队,所以还有一部分为dp[i -1].
所以最终第二种情况就是 dp[i] = dp[i -1] + dp[i - 2];(满足前提10-25)
class Solution {
public int translateNum(int num) {
// dp -- 没想到啊。。。。
// 1.定义:dp[i] --前i个数能组成的最大翻译方法数
String s = (num + "");
int n = s.length();
int[]dp = new int[n + 1];
// 2.初始化
dp[0] = 1;
dp[1] = 1;
// 3.状态转移
for(int i = 2; i < n + 1; i++){
if(s.charAt(i - 2) == '1' || (s.charAt(i - 2) == '2' && s.charAt(i - 1) <= '5'))
dp[i] = dp[i - 1] + dp[i - 2];
else
dp[i] = dp[i - 1];
}
return dp[n];
}
}
3.结果
4总结
方法非常关键!!!做题之前先算时间复杂度。思路拓宽!遇事不决选动归!