集合与字典

Set(集合)

概念

Set 是一种不包含重复值的数据结构,底层实现类似于哈希表,查找和操作的时间复杂度为 O(1)。

常见操作

const set = new Set()
 
set.add(1)
set.has(1)     // true
set.delete(1)  // true
set.has(1)     // false
set.size       // 0
 
// 数组去重
const arr = [1, 2, 2, 3, 3, 4]
const unique = [...new Set(arr)]  // [1, 2, 3, 4]

遍历

const set = new Set([1, 2, 3])
 
for (const item of set)           // 1 2 3
for (const item of set.keys())    // 1 2 3
for (const item of set.values())  // 1 2 3
for (const [k, v] of set.entries()) // [1,1] [2,2] [3,3](为兼容 Map 接口)
set.forEach(v => {})              // 1 2 3
 
// 遍历结果是有序的,按插入顺序
const s = new Set([3, 1, 2])
[...s]  // [3, 1, 2]

Map(字典)

概念

Map 是一种键值对数据结构,键可以是任意类型(对象、函数等),查找和操作的时间复杂度为 O(1)。

const map = new Map()
 
map.set('key', 'value')
map.get('key')    // 'value'
map.has('key')    // true
map.delete('key') // true
map.size          // 0
 
// 任意类型键
const obj = {}
map.set(obj, 'object value')

遍历

const map = new Map([['a', 1], ['b', 2], ['c', 3]])
 
for (const [key, value] of map)  // ['a',1] ['b',2] ['c',3]
for (const key of map.keys())    // 'a' 'b' 'c'
for (const value of map.values()) // 1 2 3
for (const [k, v] of map.entries()) // ['a',1] ['b',2] ['c',3]
map.forEach((v, k) => {})         // 1:'a' 2:'b' 3:'c'

数组去重

// Set
const unique1 = [...new Set(arr)]
 
// 双循环(不推荐)
const unique2 = []
for (const item of arr) {
  if (!unique2.includes(item)) unique2.push(item)
}
 
// 使用 Map 统计频率
const count = new Map()
for (const item of arr) {
  count.set(item, (count.get(item) || 0) + 1)
}

Set vs Map

特性SetMap
存储单值键值对
键类型值本身任意类型
插入O(1)O(1)
查找O(1)O(1)
删除O(1)O(1)
场景去重、存在性检查映射、计数、缓存

练习题

var intersection = function(nums1, nums2) {
    const set = new Set(nums1);
    const res = []
    nums2.forEach(item => {
        if(set.has(item)) {
            res.push(item)
            set.delete(item)
        }
    })
    return res
};
var isValid = function(s) {
    const map = new Map()
    map.set('(',')')
    map.set('[',']')
    map.set('{','}')
    const res = []
    for(let i = 0; i < s.length; i++) {
        if(map.has(s[i])) {
            res.push(s[i])
        } else if(s[i] === map.get(res[res.length -1])) {
            res.pop()
        } else {
            return false
        }
    }
    return res.length === 0
};
var twoSum = function(nums, target) {
    const map = new Map()
 
    for(let i = 0; i < nums.length; i++) {
        if(map.has(nums[i])) {
            return [i, map.get(nums[i])]
        }
        map.set(target - nums[i], i)
    }
};
var lengthOfLongestSubstring = function (s) {
 
    let l = 0
    let max = 0
    let set = new Set()
    for(let r = 0; r < s.length; r++) {
        while (set.has(s[r])){
            set.delete(s[l])
            l++
        }
        set.add(s[r])
        max = Math.max(max, r-l+1)
    }
 
    return max
 
};
var minWindow = function(s, t) {
    let l = 0
    let r = 0
    let map = new Map()
    let str = ''
    for(item of t) {
        map.set(item, map.get(item) ? map.get(item) + 1 : 1)
    }
    let need = map.size
    console.log(map)
    while(r < s.length) {
        if(map.has(s[r])) {
            map.set(s[r], map.get(s[r]) - 1)
            if(map.get(s[r]) === 0) {
                need -= 1
            }
        }
        console.log(map, 'l:', l , 'r:', r)
        while(need === 0){
            const curr = s.slice(l, r+1)
            console.log(curr)
            if(!str || str.length > curr.length){
                str = curr
            }
            const c2= s[l]
            if(map.has(c2)) {
                map.set(c2,map.get(c2)+1)
                if(map.get(c2)) need+=1
            }
            l++
        }
        r++
    }
 
    return str
};
  • 时间复杂度:O(m + n)
  • 空间复杂度:O(Σ),Σ 为字符集大小

相关笔记