Google面试题解说性能之七:缓存中间结果

上次已经说了fn的实现不能用来查找符合条件的n,因为这样做比前面的第一个例子中的性能比较差的那个还要差,原因就是有太多的重复计算,如果只是计算一个指定的数的结果,那么那个实现是无与匹敌的。但是我们是讲的性能优化,所以,我们就用它来做,放慢速度,然后使用其它的技巧来提高性能,这次的方法就是简单的使用缓存:
public class GoogleFn {
    private static final int MAX = 2600002;

    private static long start = System.currentTimeMillis();

    private static int[] bases = new int[15];

    private static int[] values = new int[15];

    private static int fn(int number) {
        if (number < 10) {
            return number > 0 ? 1 : 0;
        }
        String s = number + "";
        int length = s.length();
        int end = Integer.parseInt(s.substring(1, length));
        int x = s.charAt(0) - ‘0′;
        int result = 0;
        if (x == 1) {
            result = values[length - 1] + fn(end) + (end + 1);
        } else {
            result = values[length - 1] * x + bases[length - 1] + fn(end);
        }
        return result;
    }

    private static int fnOld(int number) {
        if (number < 10) {
            return number > 0 ? 1 : 0;
        }
        String s = number + "";
        int length = s.length();
        int end = Integer.parseInt(s.substring(1, length));
        int x = s.charAt(0) - ‘0′;
        int result = 0;
        if (x == 1) {
            result = (length - 1) * (int) Math.pow(10, length - 1 - 1) + fnOld(end) + (end + 1);
        } else {
            result = (length - 1) * (int) Math.pow(10, length - 1 - 1) * x + (int) Math.pow(10, length - 1) + fnOld(end);
        }
        return result;
    }

    private static void print(int n) {
        System.out.println("Find " + n + ", " + (System.currentTimeMillis() - start) + "ms");
    }

    public static void main(String[] args) {
        for (int i = 1; i < MAX; i++) {
            if (i == fnOld(i)) {
                print(i);
            }
        }
        bases[0] = 0;
        bases[1] = 10;
        values[0] = 0;
        values[1] = 1;
        for (int i = 2; i < values.length; i++) {
            bases[i] = (int) Math.pow(10, i);
            values[i] = i * (int) Math.pow(10, i - 1);
        }
        start = System.currentTimeMillis();
        for (int i = 1; i < MAX; i++) {
            if (i == fn(i)) {
                print(i);
            }
        }
    }
}
运行结果:
Find 1, 0ms
Find 199981, 1672ms
Find 199982, 1672ms
Find 199983, 1672ms
Find 199984, 1672ms
Find 199985, 1672ms
Find 199986, 1672ms
Find 199987, 1672ms
Find 199988, 1672ms
Find 199989, 1672ms
Find 199990, 1672ms
Find 200000, 1672ms
Find 200001, 1672ms
Find 1599981, 17032ms
Find 1599982, 17032ms
Find 1599983, 17032ms
Find 1599984, 17032ms
Find 1599985, 17032ms
Find 1599986, 17032ms
Find 1599987, 17032ms
Find 1599988, 17032ms
Find 1599989, 17032ms
Find 1599990, 17032ms
Find 2600000, 29875ms
Find 2600001, 29875ms
Find 1, 0ms
Find 199981, 1000ms
Find 199982, 1000ms
Find 199983, 1000ms
Find 199984, 1000ms
Find 199985, 1000ms
Find 199986, 1000ms
Find 199987, 1000ms
Find 199988, 1000ms
Find 199989, 1000ms
Find 199990, 1000ms
Find 200000, 1000ms
Find 200001, 1000ms
Find 1599981, 8563ms
Find 1599982, 8563ms
Find 1599983, 8563ms
Find 1599984, 8563ms
Find 1599985, 8563ms
Find 1599986, 8563ms
Find 1599987, 8563ms
Find 1599988, 8563ms
Find 1599989, 8563ms
Find 1599990, 8563ms
Find 2600000, 14594ms
Find 2600001, 14594ms

可以看到,我们仅仅是缓存了几个简单的中间结果,就将性能提升了一倍。另外请和第一个例子的结果对比一下,我们优化后的结果也比那个差的实现的结果大5倍。


作者: Cherami
原载: 解惑
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。
分类: Java
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值