[路飞]_夜.leetcode第268场周赛(三)

642 阅读2分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

5186. 区间内查询数字的频率

题目

请你设计一个数据结构,它能求出给定子数组内一个给定值的 频率 。

子数组中一个值的 频率 指的是这个子数组中这个值的出现次数。

请你实现 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
}