1. 获取数值极值的概念
在计算机科学中,我们常常需要获得一组数值中的最大值和最小值,这就是数值极值。获取数值极值的能力在数据分析和机器学习领域非常重要,因为往往这两种情况下最值的确定是对数据分布和算法性质确定的关键,比如归一化处理中常用的最大最小值求解(Min-Max Scaler),还有在决策树分类器中的属性选择(Attribute Selection)。
2. 暴力枚举法计算极值
最简单的方法是暴力枚举法,在一维数列中通过遍历所有元素来做,10个数的极值就需要判断20次。其大致方法如下所示:
int n = 10;
int a[n] = {1, 6, 23, 6, -2, -52, 12, 8, 8, 5};
int max_val = -1e9, min_val = 1e9;
for (int i = 0; i < n; ++i) {
max_val = max(max_val, a[i]);
min_val = min(min_val, a[i]);
}
其中,“max_val”和“min_val”表示所求的最大值和最小值,初始值设为极小值和极大值。这个算法的时间复杂度为O(n),比一些高速算法慢得多。
3. 分治算法计算极值
使用分治法,将原问题分解成若干个规模较小的子问题,然后递归求解子问题,最后合并子问题的解到原问题。时间复杂度为O(nlogn)。具体实现方法如下所示:
const int N = 5000010;
int a[N], b[N], c[N];
void merge_sort(int l, int r) {
if (l >= r) return;
int mid = (l + r) / 2;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int tot = 0, p = l, q = mid + 1;
while (p <= mid && q <= r) {
if (a[p] <= a[q]) {
b[++tot] = a[p++];
} else {
b[++tot] = a[q++];
}
}
while (p <= mid) b[++tot] = a[p++];
while (q <= r) b[++tot] = a[q++];
for (int i = l, j = 1; i <= r; ++i, ++j) a[i] = b[j];
}
int n = 10;
int main() {
for (int i = 0; i < n; ++i) {
a[i] = rand() % 1000000;
}
merge_sort(0, n - 1);
int max_val = a[n - 1], min_val = a[0];
}
其中,“merge_sort”函数实现递归分治排序,时间复杂度为O(nlogn),“max_val”和“min_val”表示所求的最大值和最小值,分别是排序后的最后一位和第一位。
4. 动态规划计算极值
使用动态规划算法,可以解决一些复杂的分治算法无法解决的问题,例如:最大连续子序列和。它的时间复杂度为O(n)。以下为实现方法:
int max_val = -1e9, min_val = 1e9;
for (int i = 0; i < n; ++i) {
max_val = max(max_val, a[i]);
min_val = min(min_val, a[i]);
}
其中,“max_val”和“min_val”分别为所求的最大值和最小值,“a[i]”即为原数列。
5. 总结
总的来说,对于一些简单的数值极值问题,我们可以采用暴力枚举法求解,但是这样会降低运算效率,所以在处理数据量大的问题时多使用分治算法或动态规划算法来求解。无论使用哪种方法,掌握求解数值极值的技巧,对于数据分析和机器学习非常有用。