插入,删除和随机访问都是 O(1) 的容器

78 阅读1分钟

image.png

代码:

  1. 想要插入,删除都是 O(1) 的话,使用 map 就好,但 map 做不到随机返回,切片可以做到随机返回,所以结构体可以是一个 map 和 切片的组合
  2. 其中 map 记录当前值和 它在切片里的下标
  3. 插入就是在切片尾部增加一个值,
  4. 删除需要通过 map 找到那个值在切片里的位置,然后让这个位置等于当前切片里面最后一个值,如此我们只需要将切片最后一个值删掉即可
  5. 删除时,map 我们需要先添加切片尾部的值和要删除的下标,然后再 delete,防止我们 delete 完之后,又被我们加回来,比如我们要删切片中最后的那个值
type RandomizedSet struct {
    nums    []int
    indices map[int]int
}

func Constructor() RandomizedSet {
    return RandomizedSet{[]int{}, map[int]int{}}
}

func (rs *RandomizedSet) Insert(val int) bool {
    if _, ok := rs.indices[val]; ok {
        return false
    }
    rs.indices[val] = len(rs.nums)
    rs.nums = append(rs.nums, val)
    return true
}

func (rs *RandomizedSet) Remove(val int) bool {
    id, ok := rs.indices[val]
    if !ok {
        return false
    }
    last := len(rs.nums) - 1
    rs.nums[id] = rs.nums[last]
    rs.indices[rs.nums[id]] = id
    rs.nums = rs.nums[:last]
    delete(rs.indices, val)
    return true
}

func (rs *RandomizedSet) GetRandom() int {
    return rs.nums[rand.Intn(len(rs.nums))]
}