刷题一个4ms的程序,代码如何优化到3ms再到2ms?

时间:2022-07-24
本文章向大家介绍刷题一个4ms的程序,代码如何优化到3ms再到2ms?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

你在打王者荣耀的时候,是否经常会遇到这种情况:和对面同位置对线的时候,自己也没有太大失误,但是为啥对面经济比我高?能够压着我打?——是我太菜了 这可能就是你们细节上的差距,别人可能对兵线、技能、英雄机制搞得更清楚,每一步都清清楚楚,刷题也是一样,同样的方法,为啥别人的比你快很多,也需要注意一下细节。

笔者最近再刷LeetCode,对于正常一道题来说,时间的耗费有两个差距:

时间复杂度的差距

时间复杂度上的差距,因为很多题正常的暴力是O(n2)甚至更慢的时间复杂度,这些方法就算能过但是时间耗费很长,如果你发现你的算法过的时间在后30%那就说明你的方法不对了。在复杂度的差距差的可能几百毫秒,几十毫秒,而快的可能是几毫秒。

细节上的差距 很多题可能大家能够想到的比较好的方法的时间复杂度可能差不多,自己也是几毫秒但是自己的排名依然在50%-60%左右,这到底是为什么呢?是因为你的细节还需要优化,你整体复杂度虽然掌握了,但是你可能多算了几次循环,几次运算。所以当条件允许你需要静下来思考下怎么样才能让自己的程序跑在前90%以上。怎样去优化这个时间。

具体

笔者就拿今天刷的这道力扣题来讲讲,力扣的第11题,思路很清晰就是从两边向中间动态压缩区间,是一个O(n)的时间复杂度。

笔者第一次使用这个写法是4ms:

public int maxArea2(int[] height) {
        int max = 0;
        int left = 0;
        int right = height.length - 1;
        while (left < right) {
            max = Math.max(max, Math.min(height[left], height[right]) * (right - left));
            if (height[left] > height[right])// 右侧更小
                right--;
            else {
                left++;
            }
        }
        return max;
    }

但是我在研究这段代码时候发现以下几点问题可以优化:

  • 使用Math.max()判断最大值最小值的时候,下面在判断是左指针右移还是右指针左移动重复判断了,我们可以手动比较大小重复利用这次计算去完成相同的操作。
public int maxArea3(int[] height) {
    int max = 0;
    int left = 0;
    int right = height.length - 1;
    while (left < right) {
        if (height[left] < height[right]) {
            max = Math.max(max, height[left] * (right - left));
            left++;
        } else {
            max = Math.max(max, height[left] * (right - left));
            right--;
        }
    }
    return max;
}

这样的一部优化之后时间来到了稳定的3ms:

还能继续优化嘛?当然能:

  • Math.max()返回double类型转成int需要一定成本,然而我们数据本身就是int类型可以直接计算。
  • 对数组取值的时候,比较取一次(两个值),计算取一次(一个值),而我们知道数组其实在内存中我们通过0号位置计算得到我们对应位置的数值,所以我们可以把3次计算减少成2次,用两个空间leftvalue和rightvalue记录左右数组位置的值。

通过上面的优化得到下面的代码:

public int maxArea4(int[] height) {
        int max = 0;
        int left = 0;
        int right = height.length - 1;
        int team = 0;
        int leftvalue=0;int rightvalue=0;
        while (left < right)  {
            leftvalue=height[left];rightvalue=height[right];
            if (leftvalue < rightvalue) {
                team = leftvalue * (right-left);
                if(max<team) {max=team;}
                left++;
            } else {
                team = rightvalue * (right-left);
                if(max<team) {max=team;}
                right--;
            }
        }
        return max;
    }

成功步入2ms大军。

还能到1ms嘛?

  • 我是暂时不能了,,各位大佬请便!

结语

虽然这些优化并没有得到质的改善,并且可能也比较初级,但是刷题的同时通过这种不断优化能够增加对计算机执行和原理的理解:哇,原来是这样。并且如果有时间养成这样的好习惯,相信不久以后,未来的调优专家就是你了!