數組去重-Map實現


 

原文地址:https://segmentfault.com/a/1190000015923301

 

問題由來

遇到一道面試題:找到數組中第一個非重復的數。

[ 1, 1, 2, 2, 3, 4, 4, 5 ]
第一個非重復的數為 3

最簡單的想法就是兩層 for 循環遍歷數組,這樣的時間復雜度是 O(n^2)。而更高效的方式,是使用hash Map,可將時間復雜降為O(n)

其實這個題目可以衍生出三個類似的問題:

  1. 數組去重
  2. 找到數組中重復的數
  3. 找到數組中第一個非重復的數

我准備用ES6中的 Map數據結構來解決這三個問題,在這之前有必要先梳理下Map的主要知識點。

Map基礎梳理

JavaScript 的對象(Object),本質上是鍵值對的集合(Hash 結構),但是傳統上只能用字符串當作鍵。這給它的使用帶來了很大的限制。為了解決這個問題,ES6 提供了 Map 數據結構。它類似於對象,也是鍵值對的集合,但是“鍵”的范圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。也就是說,Object 結構提供了“字符串—值”的對應,Map 結構提供了“值—值”的對應,是一種更完善的 Hash 結構實現。

例如Map構造函數接受一個數組作為其參數:

const map = new Map([ [1, '張三'], [2, '李四'] ]); // 0:{1 => "張三"} // 1:{2 => "李四"}

Map實例的屬性和操作方法:

  • size:返回成員總數
  • set(key, value):添加新的鍵值
  • get(key):讀取鍵對應的值
  • has(key):是否有某個鍵
  • delete(key):刪除某個鍵
  • clear():清空

Map實例的遍歷方法:

  • keys():返回鍵名的遍歷器。
  • values():返回鍵值的遍歷器。
  • entries():返回鍵值對的遍歷器。
  • forEach():遍歷 Map 的所有成員。

下面來通過代碼解決三個問題:

數組去重

去重前:[ 1, 1, 2, 2, 3, 4, 4, 5 ]
去重后:[ 1, 2, 3, 4, 5 ]

主要思路:創建一個空Map,遍歷原始數組,把數組的每一個元素作為key存到Map中,因為Map中不會出現相同的key值,所以最終得到的Map中的所有key值就是去重后的結果。

function arrayNonRepeatfy(arr) { let hashMap = new Map(); let result = new Array(); // 數組用於返回結果 for (let i = 0; i < arr.length; i++) { if(hashMap.has(arr[i])) { // 判斷 hashMap 中是否已有該 key 值 hashMap.set(arr[i], true); // 后面的true 代表該 key 值在原始數組中重復了,false反之 } else { // 如果 hashMap 中沒有該 key 值,添加 hashMap.set(arr[i], false); result.push(arr[i]); } } return result; } let arr = [1, 1, 1, 2, 3, 3, 4, 5, 5, "a", "b", "a"]; console.log(arrayNonRepeatfy(arr)); // [ 1, 2, 3, 4, 5, 'a', 'b' ]

上面最終產生的Map不僅可以達到去重的效果,而且對每一元素的重復性都做了標注,這樣想找到找到數組中重復的數就很方便了:

console.log(hashMap); /* 0:{1 => true} {key: 1, value: true} 1:{2 => false} {key: 2, value: false} 2:{3 => true} {key: 3, value: true} 3:{4 => false} {key: 4, value: false} 4:{5 => true} {key: 5, value: true} 5:{"a" => true} {key: "a", value: true} 6:{"b" => false} {key: "b", value: false} */

找到數組中重復的數

[ 1, 1, 2, 2, 3, 4, 4, 5 ]
[ 1, 2, 4 ]
接上一節末尾,既然 hashMap中記錄了每一個元素的重復情況,找到重復的數就很簡單了,遍歷最終得到的 hashMap,值為  true 對應的鍵就是重復的數:
function findRepeatNumInArray(arr) { let hashMap = new Map(); let result = new Array(); for (let i = 0; i < arr.length; i++) { hashMap.set(arr[i], hashMap.has(arr[i])) } // 得到 hashMap 后,對其進行遍歷,值為 true,對應的鍵就是重復的數 for(let [key, value] of hashMap.entries()) { if(value === true) { result.push(key); } } return result; } let arr = [1, 1, 1, 2, 3, 3, 4, 5, 5, "a", "b", "a"]; console.log(findRepeatNumInArray(arr));

找到數組中第一個非重復的數

[ 1, 1, 2, 2, 3, 4, 4, 5 ]
3
代碼與上一節的差不多,遍歷最終得到的 hashMap,第一個值為  false 對應的鍵就是第一個非重復數字:
function findFirstNonRepeat(arr) { let hashMap = new Map(); for (let i = 0; i < arr.length; i++) { hashMap.set(arr[i], hashMap.has(arr[i])) } // 找到第一個值為 false 的,就代表第一個非重復數,return 就好了 for(let [key, value] of hashMap.entries()) { if(value === false) { return key; } } return "全部重復"; } let arr = [1, 1, 1, 2, 3, 3, 4, 5, 5, "a", "b", "a"]; console.log(findFirstNonRepeat(arr));

總結,三類問題的核心其實就是:利用 Map 存儲每一個數字的重復情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM