2015-05-26 37 views
0

我正在嘗試想出一種算法來解決以下問題。瞭解使用對象作爲哈希值的JavaScript算法的複雜性

給出一組ID

var ids = [8098272281362432, 7824519999782912]; 

查找項目陣列中的所有比賽。

var people = [ 
    { 
     "id": 8098272281362432, 
     "age": 59, 
     "name": "Douglas Hunter" 
    }, 
    { 
     "id": 625873891885056, 
     "age": 1, 
     "name": "Lottie Owen" 
    }, 
    { 
     "id": 7824519999782912, 
     "age": 100, 
     "name": "Maud Wise" 
    }, 
    { 
     "id": 2561552265773056, 
     "age": 115, 
     "name": "Annie Bennett" 
    } 
]; 

方法1 我可以由idO(n log n))排序兩個陣列,然後通過兩個陣列從頂部迭代一次向下(O(n)

解決這個
var alg1 = function(people, ids) { 
    var matches = []; 

    var sortedPeople = people.sort(function(a, b) { 
    return a.id - b.id 
    }); 
    var sortedIds = ids.sort(function(a, b) { 
    return a - b 
    }); 
    var curPersonIndex = 0; 

    sortedIds.forEach(function(id) { 
    while (sortedPeople[curPersonIndex].id !== id) { 
     curPersonIndex++; 
    } 

    matches.push(sortedPeople[curPersonIndex]); 
    }); 

    return matches; 
}; 

方法2 我雖然可以用O(n)算法通過創建一個id到人的映射來改善這一點,然後我可以查找每個id的人。

var alg2 = function(people, ids) { 
    var matches = []; 

    peopleMap = {}; 

    people.forEach(function(person) { 
    //Is this O(1) or O(log n)? 
    peopleMap[person.id] = person; 
    }); 

    ids.forEach(function(id) { 
    matches.push(peopleMap[id]); 
    }); 

    return matches; 
}; 

但是,當我測試了這兩個算法似乎preform大致相同。 #1鉻更快,#2在Firefox中稍快。

http://plnkr.co/edit/FidAdBqS98RKebxaIlva?p=preview

我越來越覺得插入場成一個對象是O(log n)O(1)因爲我本來期望。我已閱讀了一些有衝突的帖子,但我不確定。我想這可能取決於瀏覽器。有沒有什麼辦法可以在JavaScript中用O(n)算法一致地解決這個問題?

+0

如果你已經工作的代碼,並希望它改善,我不知道如果HTTP://代碼審查.stackexchange.com可能是您發佈信息的最佳地點。 – jfriend00

+0

花費額外的時間來構建'peopleMap'可能會回報更多的大型數據集或者如果你曾經創建地圖,然後做重複查找。此外,它似乎並沒有像#1的排序陣列的優勢,所以我想知道爲什麼你甚至不打擾他們排序。 – jfriend00

+0

是數組更新頻繁還是隻是一次? –

回答

4

首先,JavaScript不要求將對象實現爲散列(平均值爲O(1)查找),而不是使用其他結構(如O(log(n))的BTree)。所以沒有人能保證對象屬性查找的性能。

但通常人們使用哈希值。這是O(1)

但正如笑話所說,對於所有意圖和目的,log(n)是一個常數。對於Google來說,這是一個稍微大一點的常量。捕捉到真實的真相。 log(1000)log(1000000000)之間的區別是3倍於CPU的緩存與去RAM訪問的東西之間的差別是10倍。雖然理論上O(1)O(log(n))更好,在實踐中數據的大小,我們實際上很可能會遇到,實施細節造成更大的差異。而且要麼能贏。

所以你的基準測試沒有提到理論縮放規則。而事實上,不同的實現有不同的表現獲獎者爲您的使用情況下,大約是世界上不幸的事實,你必須在工作中的一個

+0

我測試了200萬個項目。 'Log2(2000000)= 21'所以如果Aproach 1是'O(n log n)'並且方法2是'O(n)',那麼我希望看到'log n'開始有一些效果。但是這兩種算法仍然幾乎相同。所以我認爲這可能更多的是插入到一個耗費'O(log n)'的對象中,而不是'log n'太小而無法注意的情況。但是我猜這還很難說,因爲像CPU緩存這樣的其他因素可能會以這種方式獲得 – rob

+0

您真的無法將足夠的數據扔到它上面去實驗性地找出存在哪些對數因子。此外,哈希對高速緩存很難,而排序算法非常友善。作爲一個極端的例子,如果你在磁盤上有100GB的數據,那麼sort會執行很多個數量級的散列。 – btilly