📅  最后修改于: 2023-12-03 15:23:37.200000             🧑  作者: Mango
这是一个常见的问题,通常需要通过编写算法实现。以下是一些常见的算法实现,可以供程序员进行参考。
遍历给定的整数序列,将其中属于 L 到 R 范围内的元素加起来,得到总和。
def sum_between_l_and_r(arr, L, R):
result = 0
for num in arr:
if L <= num <= R:
result += num
return result
public static int sumBetweenLAndR(int[] arr, int L, int R) {
int result = 0;
for (int num : arr) {
if (num >= L && num <= R) {
result += num;
}
}
return result;
}
时间复杂度为 O(n),其中 n 为给定的整数序列的长度。
使用前缀和优化算法一,将序列的所有前缀和计算出来,对于每一个查询,只需要使用两个前缀和相减得到 L 到 R 范围内的总和。
def sum_between_l_and_r(arr, L, R):
n = len(arr)
prefix_sum = [0] * (n + 1)
for i in range(1, n + 1):
prefix_sum[i] = prefix_sum[i - 1] + arr[i - 1]
return prefix_sum[R + 1] - prefix_sum[L]
public static int sumBetweenLAndR(int[] arr, int L, int R) {
int n = arr.length;
int[] prefixSum = new int[n + 1];
for (int i = 1; i <= n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i - 1];
}
return prefixSum[R + 1] - prefixSum[L];
}
时间复杂度为 O(n),其中 n 为给定的整数序列的长度。预处理的时间复杂度为 O(n),每次查询的时间复杂度为 O(1)。
使用线段树维护序列区间和,可以进行单点修改和区间查询。
class SegmentTree:
def __init__(self, arr):
n = len(arr)
self.tree = [0] * (4 * n)
self.build(arr, 1, 0, n - 1)
def build(self, arr, curNode, left, right):
if left == right:
self.tree[curNode] = arr[left]
else:
mid = (left + right) // 2
self.build(arr, 2 * curNode, left, mid)
self.build(arr, 2 * curNode + 1, mid + 1, right)
self.tree[curNode] = self.tree[2 * curNode] + self.tree[2 * curNode + 1]
def update(self, curNode, left, right, idx, val):
if left == right:
self.tree[curNode] = val
else:
mid = (left + right) // 2
if idx <= mid:
self.update(2 * curNode, left, mid, idx, val)
else:
self.update(2 * curNode + 1, mid + 1, right, idx, val)
self.tree[curNode] = self.tree[2 * curNode] + self.tree[2 * curNode + 1]
def query(self, curNode, left, right, ql, qr):
if left > qr or right < ql:
return 0
elif ql <= left and right <= qr:
return self.tree[curNode]
else:
mid = (left + right) // 2
leftChild = self.query(2 * curNode, left, mid, ql, qr)
rightChild = self.query(2 * curNode + 1, mid + 1, right, ql, qr)
return leftChild + rightChild
def sum_between_l_and_r(arr, L, R):
n = len(arr)
tree = SegmentTree(arr)
return tree.query(1, 0, n - 1, L, R)
class SegmentTree {
private int[] tree;
public SegmentTree(int[] arr) {
int n = arr.length;
tree = new int[4 * n];
build(arr, 1, 0, n - 1);
}
private void build(int[] arr, int curNode, int left, int right) {
if (left == right) {
tree[curNode] = arr[left];
} else {
int mid = (left + right) / 2;
build(arr, 2 * curNode, left, mid);
build(arr, 2 * curNode + 1, mid + 1, right);
tree[curNode] = tree[2 * curNode] + tree[2 * curNode + 1];
}
}
public void update(int curNode, int left, int right, int idx, int val) {
if (left == right) {
tree[curNode] = val;
} else {
int mid = (left + right) / 2;
if (idx <= mid) {
update(2 * curNode, left, mid, idx, val);
} else {
update(2 * curNode + 1, mid + 1, right, idx, val);
}
tree[curNode] = tree[2 * curNode] + tree[2 * curNode + 1];
}
}
public int query(int curNode, int left, int right, int ql, int qr) {
if (ql > right || qr < left) {
return 0;
} else if (ql <= left && qr >= right) {
return tree[curNode];
} else {
int mid = (left + right) / 2;
int leftChild = query(2 * curNode, left, mid, ql, qr);
int rightChild = query(2 * curNode + 1, mid + 1, right, ql, qr);
return leftChild + rightChild;
}
}
}
public static int sumBetweenLAndR(int[] arr, int L, int R) {
int n = arr.length;
SegmentTree tree = new SegmentTree(arr);
return tree.query(1, 0, n - 1, L, R);
}
时间复杂度为 O(n log n),其中 n 为给定的整数序列的长度。建树的时间复杂度为 O(n log n),单点修改和区间查询的时间复杂度均为 O(log n)。