在最多一次替换后,最小化给定数组中波峰和波谷的数量

data structurec++programming

波峰定义为数组中左右两侧值均小于该索引值的点或索引。波谷定义为数组中左右两侧值均大于该索引值的点或索引。在本题中,我们给出了一个大小为 n 的整数数组"array"。我们的任务是通过执行一个操作来最小化或减少给定数组中波峰和波谷的数量。操作是,我们可以用任意值替换给定数组中最多一个值。

注意:在上面对问题的解释中,我们提到了波峰和波谷,因此需要明确的是,给定数组的第 0 个索引和最后一个索引既不被视为波峰,也不被视为波谷,因为它们没有相邻的元素。

示例

输入

n: 5
array: [2, 1, 3, 2, 6]

输出

0

解释:在上面给出的大小为 5 的数组中,波峰和波谷的数量为 0通过将第二个索引值 3 替换为 1。因此新数组变为 [2, 1, 1, 2, 6]。

输入

n: 6
array: [2, 1, 3, 4, 3, 4]

输出

1

贪婪方法 

这种方法的思路很简单,我们在这里采用贪婪的思维方式,因为我们知道任何索引 i 都会影响第 i+1 个或第 i-1 个索引,所以我们尝试更改受最大索引数量影响的第 i 个索引的值。

下面让我们逐步讨论这种方法-

  • 这里我们创建了三个函数:'minCountOfPeaksTrougs'、'next' 和 'previous'。

  • 在 'minCountOfPeaksTrougs' 函数中

创建一个布尔数组,通过遍历数组并计数来标记波峰和波谷。

将波峰和波谷的计数存储在变量 result 中。

再次遍历数组,检查当前索引 i 的下一个和上一个索引,方法是将当前数组值分别赋值为下一个数组值和上一个数组值,并使用 next 和 previous 函数更新结果。

最后更新结果并返回。

  • 在下一个和上一个函数

这两个函数都接受当前索引、数组和数组长度等参数,分别用于验证当前索引是否有峰值和谷值。

为了更好地理解上述方法,我们来看下面的代码。

示例

#include <bits/stdc++.h>
using namespace std;
 
// 创建一个函数来检查当前索引的下一个元素
bool next(int i, int array[], int n){
   bool ok;
   ok = i > 0 && i < n - 1 && array[i] < array[i - 1] && array[i] < array[i + 1];
   return ok;
}
// 创建一个函数来检查当前索引的前一个元素
bool previous(int i, int array[], int n){
   bool ok;
   ok = i > 0 && i < n - 1 && array[i] > array[i - 1] && array[i] > array[i + 1];
   return ok;
}
// 创建函数 minCountOfPeaksTrougs 来最小化峰值和谷值的数量
int minCountOfPeaksTrougs(int array[], int n){
    // 创建一个布尔数组来存储波峰和波谷的索引
    bool check[n] = { 0 };
    int cnt = 0;
    // 遍历给定数组以检查波谷和波峰
   for (int i = 1; i < n- 1; i++) {
      //如果两个邻居都大于当前索引,则为峰值
      if (array[i] > array[i - 1] && array[i] > array[i + 1]){
         check[i] = 1;
         cnt++;
      }
      //如果两个邻居都小于当前索引,则
      else if (array[i] < array[i - 1] && array[i] < array[i + 1]){
         check[i] = 1;
         cnt++;
      }
   }
    // 创建变量 result,并用波峰和波谷的数量进行初始化
    int result = cnt;
    // 遍历数组
   for (int i = 1; i < n - 1; i++) {
      int curVal = array[i];
      // 如果我们把当前数组值作为下一个数组值
      array[i] = array[i + 1];
      int temp = cnt -check[i - 1] -check[i] -check[i + 1] +next(i - 1, array, n) +previous(i - 1, array, n) +next(i, array, n) +previous(i, array, n) +next(i + 1, array, n) +previous(i + 1, array, n);
      result= min( result, temp );
      // 如果我们把当前数组值作为前一个数组值
      array[i] = array[i - 1];
      temp = cnt -check[i - 1] -check[i] -check[i + 1] +next(i - 1, array, n) +previous(i - 1, array, n) +next(i, array, n) +previous(i, array, n) +next(i + 1, array, n) +previous(i + 1, array, n);
      
      result= min( result, temp );
      array[i] = curVal;
   }
   return result;
}
int main(){
    // 给定数组
    int array[] = { 2, 1, 3, 2, 6 };
    // 获取给定数组的大小
    int n = sizeof(array) / sizeof(int);
    // 调用 minCountOfPeaksTrougs 函数存储峰值和谷值的最小数量
    int res = minCountOfPeaksTrougs(array, n);
    cout << "波峰和波谷的最小数量为: "<< res;
    return 0;
}

输出

波峰和波谷的最小数量为: 0

时间和空间复杂度

由于我们遍历了数组,因此上述代码的时间复杂度为 O(N)。

由于我们存储了波峰和波谷的数量,因此上述代码的空间复杂度为 O(N)。

其中 N 是数组的大小。

结论 

在本教程中,我们实现了一个 C++ 程序,用于在最多一次替换后最小化给定数组中波峰和波谷的数量。我们实现了贪婪算法。时间复杂度为 O(N),空间复杂度为 O(N)。其中 N 是数组的大小。


相关文章