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

掃一掃 關注個人微信訂閱號
相關文章
相關標籤/搜索