2021-05-15:数组为{3, 2, 2, 3, 1},查询为(0, 3, 2),意思是在数组里下标0~3这个范围上,有几个2?答案返回2。假设给你一个数组arr, 对这个数组的查询非常频繁,都给出来。请返回所有查询的结果。

福大大 答案2021-05-15:

遍历存map。map的键是数组中的值,map的值是存数组下标的数组。比如{3,2,2,3,1},保存到map里就是{3:[0,3],2:[0,1],1:[4]},然后用二分法查找某个数的索引范围。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {
    arr := []int{3, 2, 2, 3, 1}
    box := NewQueryBox2(arr)
    ret := box.query(0, 3, 2)
    fmt.Println(ret)
}

type QueryBox2 struct {
    dataMap map[int][]int
}

func NewQueryBox2(arr []int) *QueryBox2 {
    ret := &QueryBox2{}
    ret.dataMap = make(map[int][]int)
    for i := 0; i < len(arr); i++ {
        ret.dataMap[arr[i]] = append(ret.dataMap[arr[i]], i)
    }
    return ret
}

func (this *QueryBox2) query(L int, R int, value int) int {
    if _, ok := this.dataMap[value]; !ok {
        return 0
    }
    indexArr := this.dataMap[value]
    // 查询 < L 的下标有几个
    a := this.countLess(indexArr, L)
    // 查询 < R+1 的下标有几个
    b := this.countLess(indexArr, R+1)
    return b - a
}

// 在有序数组arr中,用二分的方法数出<limit的数有几个
// 也就是用二分法,找到<limit的数中最右的位置
func (this *QueryBox2) countLess(arr []int, limit int) int {
    L := 0
    R := len(arr) - 1
    mostRight := -1
    for L <= R {
        mid := L + ((R - L) >> 1)
        if arr[mid] < limit {
            mostRight = mid
            L = mid + 1
        } else {
            R = mid - 1
        }
    }
    return mostRight + 1
}

执行结果如下:
图片


左神java代码