数据结构与算法:范围查询和范围和查询的优化
数据结构与算法:范围查询和范围和查询的优化
(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的构建:
- 对数组A进行排序,得到有序数组B。
- 构建一个累计和数组C,C[i]表示B[1]到B[i]的元素之和。
- 返回数据结构C。
范围查询的算法:
- 在C中使用二分查找,找到大于x的最小元素的下标left。
- 在C中使用二分查找,找到小于等于y的最大元素的下标right。
- 返回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的构建:
- 对数组A进行排序,得到有序数组B。
- 构建一个累计和数组C,C[i]表示B[1]到B[i]的元素之和。
- 返回数据结构C。
范围和查询的算法:
- 如果x大于k或者y小于1,则返回0。
- 在C中使用二分查找,找到大于x的最小元素的下标left。
- 在C中使用二分查找,找到小于等于y的最大元素的下标right。
- 返回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 著作权归作者所有。请勿转载和采集!