xszi / javascript-algorithms

算法修炼中...
5 stars 0 forks source link

常数时间插入、删除和获取随机元素 #68

Open xszi opened 3 years ago

xszi commented 3 years ago

设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。

示例 :

// 初始化一个空的集合。
RandomizedSet randomSet = new RandomizedSet();

// 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomSet.insert(1);

// 返回 false ,表示集合中不存在 2 。
randomSet.remove(2);

// 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomSet.insert(2);

// getRandom 应随机返回 1 或 2 。
randomSet.getRandom();

// 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomSet.remove(1);

// 2 已在集合中,所以返回 false 。
randomSet.insert(2);

// 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
randomSet.getRandom();
xszi commented 3 years ago

Map + 数组

const RandomizeSet = function() {
    this.map = new Map()
    this.values = []
}

RandomizeSet.prototype.insert = function(val) {
    // 存在
    if(this.map.has(val)) {
        return false
    }
    // 不存在
    this.map.set(val, this.values.length)
    this.values.push(val)
    return true
}

RandomizeSet.prototype.remove = function(val) {
    if(!this.map.has(val)) {
        return false
    }

    const index = this.map.get(val)
    // 存在且为最后一个元素
    if(index === this.values.length - 1) {
        this.values.pop()
        this.map.delete(val)
    } else {
        // 存在不为最后一个元素,把最后一个位置的值填到删除的地方
        const lastValue = this.values.pop()
        this.values[index] = lastValue
        this.map.set(lastValue, index)
        this.map.delete(val)
    }
    return true
}

RandomizeSet.prototype.getRandom = function() {
    const length = this.values.length
    const random = Math.floor(Math.random() * length)
    return this.values[random]
}

使用Set

const RandomizeSet = function() {
    this.set = new Set()
}

RandomizeSet.prototype.insert = function(val) {
    if (this.set.has(val)) {
        return false
    }
    this.set.add(val)
    return true
}

RandomizeSet.prototype.remove = function(val) {
    if (!this.set.has(val)) {
        return false
    }
    this.set.delete(val)
    return true
}

RandomizeSet.prototype.getRandom = function() {
    const random = parseInt(Math.random() * (this.set.size))
    return [...this.set][random]
}