「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」
题目
请你设计一个数据结构,它能求出给定子数组内一个给定值的 频率 。
子数组中一个值的 频率 指的是这个子数组中这个值的出现次数。
请你实现 RangeFreqQuery 类:
RangeFreqQuery(int[] arr) 用下标从 0 开始的整数数组 arr 构造一个类的实例。
int query(int left, int right, int value)返回子数组arr[left...right]中value的频率 。
一个 子数组 指的是数组中一段连续的元素。
arr[left...right] 指的是 nums 中包含下标 left 和 right 在内 的中间一段连续元素。
示例1
输入:
["RangeFreqQuery", "query", "query"]
[[[12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]], [1, 2, 4], [0, 11, 33]]
输出:
[null, 1, 2]
解释:
RangeFreqQuery rangeFreqQuery = new RangeFreqQuery([12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]);
rangeFreqQuery.query(1, 2, 4); // 返回 1 。4 在子数组 [33, 4] 中出现 1 次。
rangeFreqQuery.query(0, 11, 33); // 返回 2 。33 在整个子数组中出现 2 次。
解题思路
暴力求解
已知数组,有数组区间[left,right]中value的数量;枚举left->right;
这样做每次query时间复杂度都为O(n);
调用query次说过多会超时,所以暴力思路无错,但是需要优化;
哈希表
数组区间[left,right]中value的数量;要求返回数量,是不是可以申请一个哈希表存储value出现出现的次数;
在调用query的时候返回value的数量,在value数量上根据left、right筛选,这样优化,每次调用query最多操作value数量次;大大降低了时间复杂度;
根据上述思路编辑代码如下
var RangeFreqQuery = function (arr) {
this.map = {}
//将数组数据存放到哈希表中
arr.forEach((n, i) => {
if (this.map[n] === undefined) {
this.map[n] = [i]
} else {
this.map[n].push(i)
}
})
}
RangeFreqQuery.prototype.query = function (left, right, value) {
//从哈希表中获取value出现的次数
const indexList = this.map[value]
if (indexList && indexList.length) {
const len = indexList.length
if (indexList[0] > right) return 0
if (indexList[len - 1] < left) return 0
let l = 0
for (let i = 0; i < len; i++) {
const idx = indexList[i]
if (idx >= left) {
l = i
break
}
}
let r = len - 1
for (let i = len - 1; i >= 0; i--) {
const idx = indexList[i]
if (idx <= right) {
r = i
break
}
}
// console.log('r,l',r,l)
return Math.max(0, r - l + 1)
}
return 0
}