|
| 1 | +// package leetcode |
| 2 | + |
| 3 | +/* |
| 4 | + * @lc app=leetcode.cn id=381 lang=golang |
| 5 | + * |
| 6 | + * [381] O(1) 时间插入、删除和获取随机元素 - 允许重复 |
| 7 | + * |
| 8 | + * https://leetcode-cn.com/problems/insert-delete-getrandom-o1-duplicates-allowed/description/ |
| 9 | + * |
| 10 | + * algorithms |
| 11 | + * Hard (34.86%) |
| 12 | + * Likes: 31 |
| 13 | + * Dislikes: 0 |
| 14 | + * Total Accepted: 1.4K |
| 15 | + * Total Submissions: 3.7K |
| 16 | + * Testcase Example: '["RandomizedCollection","insert","insert","insert","getRandom","remove","getRandom"]\n[[],[1],[1],[2],[],[1],[]]' |
| 17 | + * |
| 18 | + * 设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构。 |
| 19 | + * |
| 20 | + * 注意: 允许出现重复元素。 |
| 21 | + * |
| 22 | + * |
| 23 | + * insert(val):向集合中插入元素 val。 |
| 24 | + * remove(val):当 val 存在时,从集合中移除一个 val。 |
| 25 | + * getRandom:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。 |
| 26 | + * |
| 27 | + * |
| 28 | + * 示例: |
| 29 | + * |
| 30 | + * // 初始化一个空的集合。 |
| 31 | + * RandomizedCollection collection = new RandomizedCollection(); |
| 32 | + * |
| 33 | + * // 向集合中插入 1 。返回 true 表示集合不包含 1 。 |
| 34 | + * collection.insert(1); |
| 35 | + * |
| 36 | + * // 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。 |
| 37 | + * collection.insert(1); |
| 38 | + * |
| 39 | + * // 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。 |
| 40 | + * collection.insert(2); |
| 41 | + * |
| 42 | + * // getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。 |
| 43 | + * collection.getRandom(); |
| 44 | + * |
| 45 | + * // 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。 |
| 46 | + * collection.remove(1); |
| 47 | + * |
| 48 | + * // getRandom 应有相同概率返回 1 和 2 。 |
| 49 | + * collection.getRandom(); |
| 50 | + * |
| 51 | + * |
| 52 | + */ |
| 53 | + |
| 54 | +// @lc code=start |
| 55 | +import ( |
| 56 | + "math/rand" |
| 57 | +) |
| 58 | + |
| 59 | +type RandomizedCollection struct { |
| 60 | + Data map[int]map[int]bool // 用map存位置 |
| 61 | + Index []int |
| 62 | +} |
| 63 | + |
| 64 | +/** Initialize your data structure here. */ |
| 65 | +func Constructor() RandomizedCollection { |
| 66 | + return RandomizedCollection{ |
| 67 | + Data: map[int]map[int]bool{}, |
| 68 | + Index: []int{}, |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ |
| 73 | +func (this *RandomizedCollection) Insert(val int) bool { |
| 74 | + notFound := false |
| 75 | + if _, ok := this.Data[val]; !ok { |
| 76 | + this.Data[val] = map[int]bool{} |
| 77 | + notFound = true |
| 78 | + } |
| 79 | + this.Index = append(this.Index, val) |
| 80 | + this.Data[val][len(this.Index)-1] = true |
| 81 | + return notFound |
| 82 | +} |
| 83 | + |
| 84 | +/** Removes a value from the collection. Returns true if the collection contained the specified element. */ |
| 85 | +func (this *RandomizedCollection) Remove(val int) bool { |
| 86 | + dict, ok := this.Data[val] |
| 87 | + if !ok { |
| 88 | + return false |
| 89 | + } |
| 90 | + var target int |
| 91 | + for k := range dict { |
| 92 | + target = k |
| 93 | + break |
| 94 | + } |
| 95 | + if len(dict) <= 1 { // 清空 |
| 96 | + delete(this.Data, val) |
| 97 | + } else { |
| 98 | + delete(dict, target) |
| 99 | + } |
| 100 | + lastIdx := len(this.Index) - 1 |
| 101 | + lastVal := this.Index[lastIdx] |
| 102 | + if target < lastIdx { |
| 103 | + // 队尾的值挪到目标位然后去掉队尾 |
| 104 | + this.Index[target] = lastVal |
| 105 | + } |
| 106 | + this.Index = this.Index[:lastIdx] |
| 107 | + lastDict := this.Data[lastVal] |
| 108 | + if len(lastDict) > 0 { |
| 109 | + lastDict[target] = true |
| 110 | + delete(lastDict, lastIdx) |
| 111 | + } |
| 112 | + return true |
| 113 | +} |
| 114 | + |
| 115 | +/** Get a random element from the collection. */ |
| 116 | +func (this *RandomizedCollection) GetRandom() int { |
| 117 | + idx := rand.Intn(len(this.Index)) |
| 118 | + return this.Index[idx] |
| 119 | +} |
| 120 | + |
| 121 | +/** |
| 122 | + * Your RandomizedCollection object will be instantiated and called as such: |
| 123 | + * obj := Constructor(); |
| 124 | + * param_1 := obj.Insert(val); |
| 125 | + * param_2 := obj.Remove(val); |
| 126 | + * param_3 := obj.GetRandom(); |
| 127 | + */ |
| 128 | +// @lc code=end |
0 commit comments