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]?

我的解法结果是对的,只是超时了,这是截图:

http://img.mukewang.com/szimg/5ade64860001341608660606.jpg


谢谢老师!


写回答

1回答

liuyubobobo

2018-04-24

我只看了一下你的记忆化搜索的逻辑。你的方式相当于对每一个数字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

0
3
想不出来叫什么
非常感谢!
2018-04-25
共3条回复

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7408 学习 · 1150 问题

查看课程