LC每日一题|20240426 - 1146. 快照数组
实现支持下列接口的「快照数组」- SnapshotArray:
SnapshotArray(int length)- 初始化一个与指定长度相等的 类数组 的数据结构。初始时,每个元素都等于 0。void set(index, val)- 会将指定索引index处的元素设置为val。int snap()- 获取该数组的快照,并返回快照的编号snap_id(快照号是调用snap()的总次数减去1)。int get(index, snap_id)- 根据指定的snap_id选择快照,并返回该快照指定索引index的值。
提示:
1 <= length <= 50000- 题目最多进行
50000次set,snap,和get的调用 。 0 <= index < length0 <= snap_id <我们调用snap()的总次数0 <= val <= 10^9
题目等级:Medium
解题思路
看这个数据量暴力是肯定没戏的。
我们可以统计在每次snap中有哪些位置发生了改变,并以此维护一个记录每个位置改变的时刻与值的表。
对于每次查询,我们只需要在对应位置的表中二分找到小于等于目标snapId所对应的值返回即可。
AC代码
class SnapshotArray(private val length: Int) {
val arr = IntArray(length)
val map = Array<ArrayList<IntArray>>(length) { arrayListOf() }
val cur = HashMap<Int, Int>()
var snapId = -1
fun set(index: Int, `val`: Int) {
cur[index] = `val`
}
fun snap(): Int {
snapId++
cur.forEach {
map[it.key].add(intArrayOf(snapId, it.value!!))
}
cur.clear()
return snapId
}
fun get(index: Int, snap_id: Int): Int {
if (map[index].isEmpty() || snap_id < map[index][0][0]) return 0
var start = 0
var end = map[index].size - 1
while (start < end) {
val mid = (start + end + 1) / 2
when {
snap_id < map[index][mid][0] -> end = mid - 1
snap_id >= map[index][mid][0] -> start = mid
}
}
return map[index][start][1]
}
}
/**
* Your SnapshotArray object will be instantiated and called as such:
* var obj = SnapshotArray(length)
* obj.set(index,`val`)
* var param_2 = obj.snap()
* var param_3 = obj.get(index,snap_id)
*/
碎碎念
我恨二分!!!