leetcode 279我的动态规划解法会超时,老师可以帮我看看吗?
来源:9-3 发现重叠子问题 Integer Break
想不出来叫什么
2018-04-24
这是我的memory search方法
private int[] memo; private int recursionNumSquares(int n){ if(memo[n] == 0){ memo[n] = Integer.MAX_VALUE; for(int i = 1; i < n; i ++){ if(i * i == n){ memo[n] = 1; break; } else{ memo[n] = Math.min(memo[n],recursionNumSquares(i)+recursionNumSquares(n-i)); } } } return memo[n]; } public int numSquares(int n) { memo = new int[n + 1]; memo[1] = 1; return recursionNumSquares(n); }
这是我的动态规划解法:
public int numSquares(int n) { int[] memo = new int[n + 1]; Arrays.fill(memo, Integer.MAX_VALUE); memo[1] = 1; for(int i = 2; i <= n; i ++){ for(int j = 1; j < i; j ++){ if(j * j == i){ memo[i] = 1; break; } else memo[i] = Math.min(memo[i], memo[j]+memo[i-j]); } } return memo[n]; }
原因似乎是因为我使用了memo[i] = Math.min(memo[i], memo[j]+memo[i-j]), 而不是memo[i] = Math.min(memo[i], 1+memo[i-j * j])
我的问题是,我们似乎无法知道memo[i]一定就是1+memo[i - j*j],为什么不进行遍历,而是直接跳过很多值,选择了memo[i -j*j]?
我的解法结果是对的,只是超时了,这是截图:
谢谢老师!
写回答
1回答
-
我只看了一下你的记忆化搜索的逻辑。你的方式相当于对每一个数字n,将他所有的拆分都尝试一遍,比如对于5,会递归下去尝试1+4; 2+3; 3+2; 4+1四种情况。
首先,具有对称性,我们只看1+4; 2+3就好了。
其次,是最最重要的,在递归尝试2 + 3之前,我们就可以看到2不是一个完全平方数,所有这种情况根本不需要递归下去尝试:)
这里,我给出的参考代码,对于k,下一步去看k - i*i就好了,就是这个意思。对于每一个数字k,直接去看这个数字k减去另一个完全平方数以后的结果。看完k-1,直接去看k-4,因为k-3的意思就是要用数字3区拼这个k,但我们已经知道数字3肯定不是完全平方数了:)
我的参考代码Java版:https://github.com/liuyubobobo/Play-Leetcode/tree/master/0279-Perfect-Squares/java-0279/src
032018-04-25
相似问题