数据结构与算法:范围查询和范围和查询的优化

(a) 范围查询

设A[1..n]是一个存储n个可能不相异数的数组。范围查询指定两个整数x和y,它们构成一个区间(x, y)。范围查询的答案是A中大于x且小于或等于y的元素个数。

例如,如果A = [4, 5, 2, 6, 8, 3, 4, 4],区间(3, 6]的范围查询将返回5,因为A中有五个元素在(3, 6]中,即A[1], A[2], A[4], A[7],而A[8]。类似地,区间(7, 10)的范围查询将返回1。

数据结构C的构建:

  1. 对数组A进行排序,得到有序数组B。
  2. 构建一个累计和数组C,C[i]表示B[1]到B[i]的元素之和。
  3. 返回数据结构C。

范围查询的算法:

  1. 在C中使用二分查找,找到大于x的最小元素的下标left。
  2. 在C中使用二分查找,找到小于等于y的最大元素的下标right。
  3. 返回right - left。

时间复杂度分析:

  • 构建数据结构C的时间复杂度为O(NlogN),其中N是数组A的长度。排序数组A的时间复杂度为O(NlogN),构建累计和数组C的时间复杂度为O(N)。
  • 范围查询的时间复杂度为O(logN)。二分查找的时间复杂度为O(logN)。

(b) 范围和查询

假设A[1..n]中的数字来自给定的某个正整数k的范围[1..k]。范围和查询指定范围[1, k]中的两个整数x和y,它们构成一个区间(x, y)。范围和查询的答案是A中大于x且小于或等于y的元素之和。

例如,如果k = 9并且A = [4, 5, 2, 6, 8, 3, 4, 4],对于区间(3, 6)的范围和查询将返回23。区间(7, 10)不定义范围和查询,因为10在范围[1, 9]之外。

数据结构C的构建:

  1. 对数组A进行排序,得到有序数组B。
  2. 构建一个累计和数组C,C[i]表示B[1]到B[i]的元素之和。
  3. 返回数据结构C。

范围和查询的算法:

  1. 如果x大于k或者y小于1,则返回0。
  2. 在C中使用二分查找,找到大于x的最小元素的下标left。
  3. 在C中使用二分查找,找到小于等于y的最大元素的下标right。
  4. 返回C[right] - C[left-1]。

时间复杂度分析:

  • 构建数据结构C的时间复杂度为O(NlogN),其中N是数组A的长度。排序数组A的时间复杂度为O(NlogN),构建累计和数组C的时间复杂度为O(N)。
  • 范围和查询的时间复杂度为O(1)。二分查找的时间复杂度为O(logN),由于我们只需要进行两次二分查找,所以总的时间复杂度为O(logN)。累计和数组C的构建也只需要O(N)的时间,因此范围和查询可以在O(1)时间内回答。

伪代码:

(a) 范围查询

# 构建数据结构C
def build_range_query_structure(A):
    B = sorted(A)
    C = [0] * (len(B) + 1)
    for i in range(1, len(B) + 1):
        C[i] = C[i - 1] + B[i - 1]
    return C

# 范围查询
def range_query(C, x, y):
    left = binary_search(C, x, 0, len(C) - 1)
    right = binary_search(C, y, 0, len(C) - 1)
    return right - left

# 二分查找
def binary_search(C, target, left, right):
    while left <= right:
        mid = (left + right) // 2
        if C[mid] > target:
            right = mid - 1
        else:
            left = mid + 1
    return left

(b) 范围和查询

# 构建数据结构C
def build_range_sum_structure(A):
    B = sorted(A)
    C = [0] * (len(B) + 1)
    for i in range(1, len(B) + 1):
        C[i] = C[i - 1] + B[i - 1]
    return C

# 范围和查询
def range_sum_query(C, x, y, k):
    if x > k or y < 1:
        return 0
    left = binary_search(C, x, 0, len(C) - 1)
    right = binary_search(C, y, 0, len(C) - 1)
    return C[right] - C[left - 1]

# 二分查找
def binary_search(C, target, left, right):
    while left <= right:
        mid = (left + right) // 2
        if C[mid] > target:
            right = mid - 1
        else:
            left = mid + 1
    return left

原文地址: https://www.cveoy.top/t/topic/3MY 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录