一次目標是演算法的征途

老喵家小喵發表於2018-06-25

遙想2016年初,在我剛剛從一個ACMer轉成一個FEer的時候,基本上js的api是記不住幾個的。

當時看著培訓的同學可以寫出Array.prototype.slice.call(……)這樣一長串不知道要幹什麼用的程式碼的時候,我只能暗暗感嘆

這就是大佬吧

當時乖巧又單純的我,連api都記不住,自然也不知道它的時間複雜度。

直到!!! 時間線回到2018年。

那天,師兄興高采烈的指著一本書上的程式碼對我說,“你看它時間複雜度可以從 O(m * n) 優化成 O(m + n) !”

然後我看了一下他所謂的 O(m + n),呃嗯嗯嗯,這不是大暴力麼???

alt

雖然工作中沒啥用,但作為一隻演算法汪,決定和師兄一起學習一些真正有趣的演算法。

思考了一下,HDU什麼的不支援js來做題,扔給師兄多少有點殘忍(說的像你自己還會用C++做題似的……)

所以就開啟了LeetCode,秉承著從簡單的開始的原則,然後選擇了通過率最高的一道題…咳…從簡單開始……

題目文藝的說法是——你有一份珠寶圖鑑,你對著圖鑑看看手裡這堆石頭有多少個是珠寶。不文藝的說法呢,不文藝的自己讀題去……

這麼高的通過率,顯然題目也是沒有坑的,我用老母親的眼神看著自己行雲流水寫出的一串程式碼自然的AC了。

let numJewelsInStones = function(J, S) {
    return S.split("").filter(item => J.includes(item)).length;
};
複製程式碼

師兄也AC了之後,我們互相看程式碼

(根本沒什麼好看的好麼!)

原以為實現方式差不多,沒想到師兄說我,你這不是用js的思維作弊麼。

看了一下師兄的程式碼,他認認真真的自己實現了一個map,然後再遍歷去查詢了一遍。

認真的思考了一下我之前寫C++時候的思維

然後,啥也沒想起來。

又看了看自己的程式碼,split的時間複雜度是多少??includes應該是 O (n) 的吧?忐忑的心情中,我去看了一下runtime的榜,60ms,打敗96%,看起來不慢誒……

alt

本來這道簡簡單單的題可能就這麼的翻頁了,但是這個榜它冥冥之中帶領著我,就這麼峰迴路轉的,走上了另一條路……

這個排名第一的人,他是這麼寫的

alt

那麼問題來了,這他喵的indexOf怎麼就比includes快出了8ms???

此時,麻煩剪輯老師切成16年和18年的對比,兩年後的我依舊不能確切的說出這個api的時間複雜度。

好的吧,我不知道肯定是有大佬知道的。

我就隨意的在某度上搜了一下,emmm,沒有??好吧,垃圾,換Google肯定就能搜到了呢。

emmm?為啥還是沒有?

……

……

……

遙想起當年在實驗室中,學長們口口相傳的告訴我們經典的api的時間複雜度的場景,我決定,去看底層的實現來把這個搞清楚!

在我下這個決定的時候,我甚至覺得苦苦尋覓不到的分享主題有了!

alt

好好好,好吧。

所以就去看實現吧!大概是一種初生牛犢不怕虎的精神,當時的我決定去看V8的實現。

在github上找了V8的原始碼,隨意的翻了一下,就看到了這裡 ↓↓↓

(function(global, utils, extrasUtils) {
    "use strict";
    %CheckIsBootstrapping();
    // -------------------------------------------------------------------
    // Imports
    var GlobalArray = global.Array;
    ……
    ……
    var ArrayIndexOf = GlobalArray.prototype.indexOf;
    var ArrayJoin = GlobalArray.prototype.join;
    var ArrayPop = GlobalArray.prototype.pop;
    ……
    utils.SetUpLockedPrototype(InternalArray, GlobalArray(), [
      "indexOf", ArrayIndexOf,
      "join", ArrayJoin,
      ……
]);
複製程式碼

欣喜之餘,問題來了,global在哪裡傳過來的?

看著一個凌亂的C++專案,我思考了兩分鐘之後,決定把程式碼clone下來! (內心os:到時候全域性搜一下就好了嘛)

半天之後,終於下載好了專案 我搜~

alt

再搜~

alt

就這樣,經過了一波搜尋加檢視後,我選擇開啟了ECMA-262的文件。

看著有些熟悉的文件……

為什麼熟悉呢?因為之前大佬組織了一波翻譯ECMA-262文件的活動,還在實習我的開開心心的報名了,然後淚流滿面的翻譯完了ECMA-262的第七章,請為乖巧的我點贊,靴靴

文章當時發在眾成翻譯上,說到這裡不得不說,眾成翻譯真的好用,特別適合一些沒經驗還想鍛鍊英文翻譯能力的萌新。我,喵喵,實名為眾成翻譯安利……

好的,回到正題,文件中有句話是這麼說的

The includes method intentionally differs from the similar indexOf method in two ways. First, it uses the SameValueZero algorithm, instead of Strict Equality Comparison, allowing it to detect NaN array elements. Second, it does not skip missing array elements, instead treating them as undefined.

仔細的看了看 SameValueZero 方法和 Strict Equality Comparison 之後,貌似沒什麼影響?

這時候福至心靈的我,回到了LeetCode,複製了第一的程式碼,貼上,提交。

alt

好的,拜拜。【摔!】

相關文章