如果每选择两个元素,第三个元素是免费选择的,则最小化数组的成本

data structurec++programming

这个问题给我们一个数组,我们需要以最低的成本移除数组中的所有元素。我们需要一次移除两个元素,并将它们添加到总成本中。此外,如果我们移除两个元素,并且第三个元素的值最多等于其中的最小值,那么我们可以免费移除第三个数字。此外,给定数组的大小必然大于 1。

示例

输入

int arr[] = {7, 6, 5, 2, 9, 2};

输出

23

解释:我们可以同时移除 9 和 7 来移除 6,这将花费 16。然后,我们可以同时移除 5 和 2,这将免费移除另外 2,此操作的总成本为 7,总成本为 23。

输入

int arr[] = {1, 2, 3, 4};

输出

10

解释:我们可以先移除 4 和 3,然后再移除 2,但这会导致第一个元素 1 单独出现,因此我们无法移除它。因此,我们不会将 2 与 4 和 3 一起移除,移除 1 会导致总成本为 10。

方法 1:使用排序

在此方法中,我们将对数组进行排序,然后从后端遍历。我们将传入三个元素组成的数组,并仅添加前两个元素的成本,直到达到 4 或两个元素,然后我们仅添加两个元素组成的数组。

示例

#include <bits/stdc++.h>
using namespace std;
// 用于查找所需最小成本的函数
int requiredCost(int arr[], int len){
    // 使用 stl sort 函数对给定数组进行排序
    sort(arr, arr + len);
    int cost = 0; // 用于存储从数组后端遍历成本的变量
	for (int i = len- 1; i>= 0; i--){
	   // i 为 3 或 1 表示剩余 4 和 2 个元素,我们只能按组选择,不能删除第三个
	   if(i == 3 || i == 1){
	      cost += arr[i] + arr[i-1];
	      i--;
	   } else{
	      // 我们将丢失第 i 个和第 i-1 个元素
	      cost += arr[i] + arr[i-1];
	      i -= 2; 
	   }
	}	
	return cost; // 返回总成本
}
int main(){
    int arr[] = { 6, 5, 7, 9, 2, 2 }; // 给定数组
    int len = sizeof(arr)/ sizeof(arr[0]); // 获取数组长度
    cout<<"删除数组中所有元素的最小成本为 "<< requiredCost(arr, len)<<endl;
return 0;
}

输出

删除数组中所有元素的最小成本为 23

时间和空间复杂度

上述代码的时间复杂度为 O(N*log(N)),其中 N 是给定数组中的元素数量。我们使用内置排序函数,这会消耗对数因子。

上述代码的空间复杂度为 O(1) 或常数,因为我们这里没有使用任何额外的空间。

方法 2:使用 Map

在本程序中,我们将使用 Map 并从 Map 的最后一个元素中获取元素,每次我们将按 3 个元素为一组的方式获取元素。在前面的代码中执行,然后对于 4 和 2 元素,我们将只创建 2 个组。

示例

#include <bits/stdc++.h>
using namespace std;

int requiredCost(int arr[], int len){
   int cost = 0; // 存储成本的变量
   map<int,int>mp;
   // 遍历数组并向 map 添加元素
   for(int i=0; i<len; i++){
      mp[arr[i]]++;
   }
    // 遍历 map
    int rem_elements = len; // 用于跟踪剩余变量的变量
    // 遍历 map 直到 rem_elements 退出
   while(rem_elements > 0){
      if(rem_elements == 4 || rem_elements == 2){
         auto it = mp.rbegin();
         if(it->second > 1){
            // remove 2 elements 
            cost += 2*it->first; 
            it->second -= 2;
            rem_elements -= 2; // 删除了 2 个元素
            if(it->second == 0){
               mp.erase(it->first);  // remove from map
            }
         } else{
            // 移除当前元素
            cost += it->first;
            mp.erase(it->first);
            it = mp.rbegin();
            cost += it->first;
            if(it->second == 1){
               mp.erase(it->first);
            }
            rem_elements -= 2; // 删除了 2 个元素
         }
      } else{
         // 现在我们可以删除三个元素
         int k = 3; 
         while(k > 0){
            auto it = mp.rbegin();
            if(k > 1){
               cost += it->first; 
            }
            it->second--;
            if(it->second == 0){
               mp.erase(it->first);
            }
            k--;
         }
         rem_elements -= 3;
      }
   }
	return cost; // 返回总成本
}
// 主函数
int main(){
    int arr[] = { 6, 5, 7, 9, 2, 2 }; // 给定数组
    int len = sizeof(arr)/ sizeof(arr[0]); // 获取数组长度
    // 调用函数
    cout<<"删除数组所有元素的最小成本为 "<< requiredCost(arr, len)<<endl;
    return 0;
}

输出

删除数组中所有元素的最小成本为 23

时间和空间复杂度

上述代码的时间复杂度为 O(N*log(N)),因为我们使用了 map 来存储、移除和删除元素。

上述代码的空间复杂度为 O(N),其中 N 是给定数组的大小,额外的空间因素是由于 map 造成的。

结论

在本教程中,我们实现了一个程序,用于计算从数组中删除元素的最小成本,如果可能的话,以 3 个元素为一组;否则,以 2 个元素为一组。其中,删除 3 个元素的组中元素的成本仅为最大两个元素之和。我们实现了两个程序,时间复杂度为 O(N*log(N)),空间复杂度为 O(1) 和 O(N)。


相关文章