你在打王者荣耀的时候,是否经常会遇到这种情况:和对面同位置对线的时候,自己也没有太大失误,但是为啥对面经济比我高?能够压着我打?——是我太菜了 这可能就是你们细节上的差距,别人可能对兵线、技能、英雄机制搞得更清楚,每一步都清清楚楚,刷题也是一样,同样的方法,为啥别人的比你快很多,也需要注意一下细节。
笔者最近再刷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;
}
但是我在研究这段代码时候发现以下几点问题可以优化:
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:
还能继续优化嘛?当然能:
通过上面的优化得到下面的代码:
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嘛?
虽然这些优化并没有得到质的改善,并且可能也比较初级,但是刷题的同时通过这种不断优化能够增加对计算机执行和原理的理解:哇,原来是这样。并且如果有时间养成这样的好习惯,相信不久以后,未来的调优专家就是你了!