【发布时间】:2021-11-13 00:37:31
【问题描述】:
假设我得到了以下数组
a = [4 5 2 1 3 4]
我想找出两个元素(最大值和最小值)之间的差异,不包括一些连续元素。
例如排除第2个和第3个这样我需要找到max/min的差异:
a = [4 1 3 4]
在这种情况下是
diff = 4-1
现在我正在寻找一种可以反复执行此操作的有效算法。 我正在考虑有一个前缀和后缀,但不知道如何前进
【问题讨论】:
假设我得到了以下数组
a = [4 5 2 1 3 4]
我想找出两个元素(最大值和最小值)之间的差异,不包括一些连续元素。
例如排除第2个和第3个这样我需要找到max/min的差异:
a = [4 1 3 4]
在这种情况下是
diff = 4-1
现在我正在寻找一种可以反复执行此操作的有效算法。 我正在考虑有一个前缀和后缀,但不知道如何前进
【问题讨论】:
所以我们有一个大小为N 和M 的数组a 查询这种形式:“排除区间[L, R],a 中的最大和最小元素有什么区别?” .考虑我们有一种有效的方法来查询任意间隔[X, Y] 上的最小值和最大值,那么我们可以使用以下算法:
[0, L)的最小值/最大值
(R, N)的最小值/最大值
后期编辑:我最初提出了一个比必要的复杂得多的解决方案。如果您对其他方法感到好奇,我会留下它,但这里是一种更简单的方法。
我们知道我们总是只查询[0, something) 和(something, N) 形式的区间,我们可以在线性时间内预先计算最小值/最大值。考虑像这样存储它们:
min_from_left[i] = minimum item considering only items 0..i
min_from_right[i] = minimum item considering only items i..N
same for max
现在,不包括区间[L, R] 的最小值是min(min_from_left[L-1], min_from_right[R+1])(我省略了绑定检查)。因此,您可以实现O(N) 进行预计算和O(1) 每次查询。
通用(但不必要的方法)
要找到给定时间间隔内的最小值/最大值,您有很多选择,这取决于您的时间和内存限制以及是否需要更新:
一般来说,如果你需要更新,你可以获得O(N + M * log N)的时间复杂度,如果你不需要更新,你可以获得O(N log N + M)。
【讨论】:
只需扫描阵列。存储最小值和最大值,同时忽略排除的值。
【讨论】:
这行得通吗?
#include <iostream>
using namespace std;
int main()
{
int arr[6] = { 4, 5, 2, 1, 3, 4 };
int max = arr[0], min = arr[0];
int first, second;
cout << "Enter Range (first value): ";
cin >> first; // in your example, first = 1
cout << "Enter Range (last value): ";
cin >> second; // second = 2, in your example.
for (int i = 0; i < 6; i++)
{
if (i >= first && i <= second)
continue;
if (arr[i] < min)
min = arr[i];
if (arr[i] > max)
max = arr[i];
}
cout << "Difference between max and min is " << max - min << endl;
return 0;
}
【讨论】:
first 和second 在同一个数组上运行多次,尽管后者的区别总是相同的。一个例子是有一个包含 1000000 个元素的数组,你需要找到一个最佳部分,在给定排除数的情况下最小化 max 和 min 之间的差异。