LeetCode进阶-彩蛋一

概要

关于“彩蛋”,数据结构与算法系列博客中,若有可能,博主尽可能会在每一篇博客里埋下彩蛋。彩蛋的意义在刚开始写博客的开篇有说明过,实际就是算法实现过程的一些小技巧,而这些小技巧每每都是能够改进执行效率的。关于全部的彩蛋都会有特别的解释说明,千里之行始于足下,共勉~html

LeetCode进阶1086-Hash思想

彩蛋

仔细观察上述两种思路的实现代码会发现,有几处for循环的时候使用的都是++i
复制代码

说明

在循环次数不是特别大的时候++i比i++执行效率高,直接上代码:算法

public static void main(String[] args) {
		long start1 = System.nanoTime();
		for (int i = 0; i < 1000; i++) {

		}
		System.out.println("i++ use time(ms):" + Long.toString((System.nanoTime() - start1) / 1000));

		long start2 = System.nanoTime();
		for (int i = 0; i < 1000; ++i) {

		}
		System.out.println("++i use time(ms):" + Long.toString((System.nanoTime() - start2) / 1000));
	}
复制代码
  • 循环次数1000
i++ 耗时(ms):24
++i 耗时(ms):9
复制代码
  • 循环次数10000
i++ 耗时(ms):68
++i 耗时(ms):46
复制代码
  • 循环次数100000
i++ 耗时(ms):595
++i 耗时(ms):576
复制代码
  • 循环次数1000000
i++ 耗时(ms):1370
++i use time(ms):2157
复制代码

能够看到:大概在100000次循环以前,++i的效率优于i++;而在1000000的时候i++则优于++i,看到网上不少博客千篇一概的结论是同样实际是错误的,固然博主也验证了二者的字节码确实也是同样:数组

  • 源码
public static void test1() {
		for (int i = 0; i < 1000; i++) {

		}
	}

	public static void test2() {
		for (int i = 0; i < 1000; ++i) {

		}
	}
复制代码
  • 字节码
public static void test1();
    Code:
       0: iconst_0
       1: istore_0
       2: iload_0
       3: sipush        1000
       6: if_icmpge     15
       9: iinc          0, 1
      12: goto          2
      15: return

  public static void test2();
    Code:
       0: iconst_0
       1: istore_0
       2: iload_0
       3: sipush        1000
       6: if_icmpge     15
       9: iinc          0, 1
      12: goto          2
      15: return
复制代码

测试的结果在循环次数较小的时候大约100000次如下,++i更高效。那么到底该如何选择,我的建议根据实际项目中的循环次数作估计,能够写个简单UT测试。同样的字节码执行的效率不同的缘由在于JVM编译器,在源码Java文件最终编译成机器码的过程是有细微差异的,具体差异本文暂不分析。对编译器编译感兴趣的能够先参考JVM基础系列第4讲:从源代码到机器码,发生了什么?bash

LeetCode进阶1025-动态规划

彩蛋

仔细观察第二种方法实现的时候,并非使用N % 2 == 0来判断奇偶,而是经过(N & 1) == 0来判断
复制代码

说明

"&"与运算 二进制码的每一位进行与运算,只有两位同时为1时结果为1,其他均为0。所以在N & 1时若结果为0则说明N最后一位必然为0,而二进制最后一位为0必然是2的倍数即偶数。"&"与运算比"%"模运算快的缘由是,与运算直接对整数在内存中的二进制位进行操做,所以执行效率高。比较简单,本篇不作实际验证。想要深刻学习位运算,推荐位运算有什么奇技淫巧?微信

LeetCode进阶1029-贪心

彩蛋

观察上面实现代码会发如今sort数组中存储前往B和A城市int差价和在costs数组中下标位置时,使用了左移8位再加i的操做
复制代码

说明

int整数为4字节32位,本题肯定数字在1~1000之间小于2的10次方,即数字大小转化为二进制小于11位,左移8位至关于当前数字扩大2的8次方倍,再加当前索引值i,而i同理在1~100之间转化为二进制显然低于8位。本质上移位再加索引是为了保证数字大小相对关系不变的状况还存储当前的索引下标,这样方便排序,排序的结果与不进行位移加索引操做的结果是一致的,因为相对简单,本篇再也不验证。数据结构

LeetCode进阶944-算法优化

彩蛋

进阶版对比普通版效率上有质的提升,主要是将双重for循环的内存循环拆成了独立的方法
复制代码

944的彩蛋分析因为流程相对复杂,后续会单独开一篇博客进行详细说明,敬请期待^_^jvm

扫一扫 关注个人微信订阅号
相关文章
相关标签/搜索