给定一个由N个数字组成的数组(不一定排序)。我们可以将任意两个数字合并成一个数字,合并这两个数字的成本等于它们的值之和。任务是找到合并所有数字的总最小成本。
例如: 假设数组A=[1,2,3,4], 我们可以移除1和2,将它们相加并将总和保留在数组中,此步骤的成本为(1+2)=3。 然后,A=[3,3,4],成本=3 在第二步中,我们可以将3和3相加,并将总和保留在数组中。此步骤的成本为(3+3)=6。 然后,A=[4,6],成本=6 在第三步中,我们可以再次从数组中移除这两个元素并将总和保留在数组中。此步骤的成本为(4+6)=6。 现在,A=[10],成本=10 因此,总成本为19(10+6+3)。 我们需要选择2个最小的元素来最小化总成本。使用最小堆结构是简单的方法。我们将能够以O(1)的时间获取最小元素,插入操作为O(log n)。 这种方法的时间复杂度为O(n log n)。
但我尝试了另一种方法,并且无法找到它失败的实例。基本思路是,我们在任何时候选择的两个最小元素的和将始终大于之前选择的元素对的总和。因此,“temp”数组将始终保持排序,我们将能够以O(1)的时间访问最小元素。 由于我对输入数组进行了排序,然后简单地遍历数组,因此我的方法的复杂度是O(n log n)。
例如: 假设数组A=[1,2,3,4], 我们可以移除1和2,将它们相加并将总和保留在数组中,此步骤的成本为(1+2)=3。 然后,A=[3,3,4],成本=3 在第二步中,我们可以将3和3相加,并将总和保留在数组中。此步骤的成本为(3+3)=6。 然后,A=[4,6],成本=6 在第三步中,我们可以再次从数组中移除这两个元素并将总和保留在数组中。此步骤的成本为(4+6)=6。 现在,A=[10],成本=10 因此,总成本为19(10+6+3)。 我们需要选择2个最小的元素来最小化总成本。使用最小堆结构是简单的方法。我们将能够以O(1)的时间获取最小元素,插入操作为O(log n)。 这种方法的时间复杂度为O(n log n)。
但我尝试了另一种方法,并且无法找到它失败的实例。基本思路是,我们在任何时候选择的两个最小元素的和将始终大于之前选择的元素对的总和。因此,“temp”数组将始终保持排序,我们将能够以O(1)的时间访问最小元素。 由于我对输入数组进行了排序,然后简单地遍历数组,因此我的方法的复杂度是O(n log n)。
int minCost(vector<int>& arr) {
sort(arr.begin(), arr.end());
// temp array will contain the sum of all the pairs of minimum elements
vector<int> temp;
// index for arr
int i = 0;
// index for temp
int j = 0;
int cost = 0;
// while we have more than 1 element combined in both the input and temp array
while(arr.size() - i + temp.size() - j > 1) {
int num1, num2;
// selecting num1 (minimum element)
if(i < arr.size() && j < temp.size()) {
if(arr[i] <= temp[j])
num1 = arr[i++];
else
num1 = temp[j++];
}
else if(i < arr.size())
num1 = arr[i++];
else if(j < temp.size())
num1 = temp[j++];
// selecting num2 (second minimum element)
if(i < arr.size() && j < temp.size()) {
if(arr[i] <= temp[j])
num2 = arr[i++];
else
num2 = temp[j++];
}
else if(i < arr.size())
num2 = arr[i++];
else if(j < temp.size())
num2 = temp[j++];
// appending the sum of the minimum elements in the temp array
int sum = num1 + num2;
temp.push_back(sum);
cost += sum;
}
return cost;
}
这种方法正确吗?如果不正确,请告诉我我漏掉了什么,以及该算法失败的测试用例。