【leetcode】380. O(1) 时间插入、删除和获取随机元素

137 阅读1分钟

leetocde-380.png

对于这一题刚开始的考虑,用set就可以解决了,setadd has remove操作的时间复杂度都是1,但是在随机获取数字这个上面,我的操作的时间复杂度不是1,而是n

错误的题解

getRandom方法处理的时候存在问题, 在每次获取随机数的时候都会创建一个数组,这个的时间、空间复杂度是n,所以不符合题目条件

var RandomizedSet = function () {
    this.set = new Set()
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.insert = function (val) {
    if (this.set.has(val)) {
        return false
    } else {
        this.set.add(val)
        return true
    }
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.remove = function (val) {
    if (this.set.has(val)) {
        this.set.delete(val)
        return true
    } else {
        return false
    }
};

/**
 * @return {number}
 */
RandomizedSet.prototype.getRandom = function () {
    let odd = Math.floor(Math.random() * this.set.size)
    let array = Array.from(this.set)
    return array[odd]
};

优化

这里用list来优化getRandom函数
这里利用list来存储数据,用maphas来查询是否存在,这里的insert以及remove都是利用了has的特性
在存储的时候,mapkey存放是题目给定的值,mapvalue是当前值在list中的索引
利用好这一点,在插入的时候,需要更新map中的value值,也就是索引
在删除的时候,需要将list值中的最后一个元素放在index

这里的map以及list就是反向映射
map[value, index]
list[index, value]

var RandomizedSet = function () {
    this.map = new Map()
    this.list = []
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.insert = function (val) {
    if (this.map.has(val)) return false
    this.map.set(val, this.list.length)
    this.list.push(val)
    return true
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.remove = function (val) {
    if (!this.map.has(val)) return false
    let index = this.map.get(val)
    let lastElement = this.list[this.list.length - 1]
    this.list[index] = lastElement
    this.map.set(lastElement, index)

    this.list.pop()
    this.map.delete(val)
    return true
};

/**
 * @return {number}
 */
RandomizedSet.prototype.getRandom = function () {
    let odd = Math.floor(Math.random() * this.list.length)
    return this.list[odd]
};