我在测试中遇到了这个问题。
给定一个数组,以最低的成本将数组减少为单个元素。要减少,请从数组中删除两个元素,添加这两个数字并将总和保留在数组中。每项操作的成本是该步骤中删除的元素的总和。
示例,让数组A = [1,2,3]
然后,我们可以删除1和2,添加它们并将总和保留在数组中。此步骤的成本为(1 + 2)= 3。
所以A = [3,3],成本= 3
在第二步中,我们可以从数组中删除这两个元素,并将总和再次保留在数组中。这一步的成本是3 + 3 = 6。
所以,A = [6],成本= 6
因此总费用为9(6 + 3)。
我尝试对数组进行排序,并将元素从逐渐增加到增加,但如果存在重复元素则会失败。
我的算法的伪代码
sort(Array)
cost = 0
for(i=0; i<Array.length - 1; i++) {
Array[i+1] = Array[i] + Array[i+1]
cost = cost + Array[i+1]
}
上面提到的算法不起作用。我想出了一个可能会失败的案例。 如果Array = [5,5,5,5],则Cost = 45,根据上述算法。
然而,如果我们将前两个元素和最后两个元素相加,然后将剩余的两个元素相加,则总成本为40.(第一步,成本= 10 * 2,下一步另一个20)
这可能是一个有效的算法吗?
答案 0 :(得分:5)
您在正确的轨道上排序数组并首先汇总最低元素。问题是:两个最低元素之和可能大于之后的下一个元素,所以你不能把它放在前面。但它也可以比最后一个元素小,所以你也不能把它放在后面。你必须把这笔钱放在它所属的地方w.r.t.排序。
示例:如果您的列表为[1, 1, 3, 3]
,那么1+1
应放在前面,即[2, 3, 3]
,但如果我们有[2, 2, 3, 3]
,那么总和{{ 1}}必须放在后面2+2
,而[3, 3, 4]
必须放在中间位置,即[2, 2, 3, 5]
。
一种简单的方法是使用heap结构。这些在大多数语言中都可用,并提供了获取和删除最小元素以及在正确位置插入元素的方法。这是Python中的一个例子:
[3, 4, 5]
如果您不能使用堆,您仍然可以迭代数组以找到放置求和元素的正确位置,或者使用二进制搜索来更快地执行此操作。
答案 1 :(得分:2)
您的数组将始终缩减为其所有元素的sum
。 "cost
&#34;这种减少可能会有所不同。
通过添加当前存在于数组中的两个最小元素,可以实现最小"cost"
。
最小堆可用于非常有效地解决此问题。这是java中的一个例子。
public int[] sumAndCost(Integer[] arr) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(Arrays.asList(arr));
int sum = priorityQueue.poll();
int cost = 0;
while (!priorityQueue.isEmpty()) {
int currentElement = priorityQueue.poll();
if (currentElement < sum) {
priorityQueue.add(sum);
sum = currentElement;
} else {
sum += currentElement;
cost += sum;
continue;
}
sum += priorityQueue.poll();
cost += sum;
}
return new int[] {sum, cost};
}
它返回任何给定数组的总和和成本。
条件语句可能看起来有点不合理,但它在一定程度上改善了我们的运行时间。
答案 2 :(得分:1)
使用@tobias_k进行精彩的解释。我的解决方案仅使用列表,
`
public static int ageMeth(String dob) {
return Period.between(LocalDate.parse(dob, DateTimeFormatter.ofPattern("MM/dd/yyyy")),
LocalDate.now()).getYears();
}
`
答案 3 :(得分:1)
首先,对数组进行排序。
第二,循环这一步,直到数组中只剩下两个元素。
第三,返回数组中剩余的两个元素的总和。
function sortedIndex(array, value) {
let low = 0, high = array.length;
while (low < high) {
let mid = (low + high) >>> 1;
if (array[mid] < value) low = mid + 1;
else high = mid;
}
return low;
}
function reductionCost(num) {
let cost = 0;
num.sort((a, b) => {
return a - b;
});
while (num.length > 2) {
const newValue = num.shift() + num.shift();
cost += newValue;
const newIndex = sortedIndex(num, newValue);
num.splice(newIndex, 0, newValue);
}
return cost + num[0] + num[1];
}
console.log(reductionCost([1, 2, 3]));
console.log(reductionCost([5, 5, 5, 5]));
答案 4 :(得分:0)
这是我在Java中的解决方案:
int cost = 0;
for (int i=1; i<Array.length; i++) {
Array[i] += Array[i-1];
cost += Array[i];
}
return cost;
答案 5 :(得分:0)
#
# Complete the 'reductionCost' function below.
#
# The function is expected to return an INTEGER.
# The function accepts INTEGER_ARRAY num as parameter.
#
from bisect import insort
def makeReduction(num):
first = num[0]
second = num[1]
cost = first+second
del num[:2]
insort(num,cost)
return cost
def reductionCost(num):
# Write your code here
if len(num) <= 1:
return 0
num.sort()
totalCost = 0
while len(num) >= 2:
totalCost += makeReduction(num)
print(totalCost)
len(num)
return totalCost
答案 6 :(得分:0)
PriorityQueue是基于优先级堆的无界队列,默认情况下,优先级队列的元素以自然顺序排序。[1]
优先级队列的头是基于自然排序或基于比较器排序的最小元素,如果有多个具有相同排序的对象,则它可以随机轮询其中的任何一个。当我们轮询队列时,它从队列中返回头对象。[1]
因此,如果我们举一个例子,其中数组arr[] = [5,5,5,5,5]
运作方式如下:
注意:以下迭代仅用于演示目的。 PriorityQueue可能没有相同的顺序,但是可以确保在轮询时给出最小的元素
Queue : 5 5 5 5 5
Iteration 1 : 5 5 5 10 :- Cost: 10
Iteration 2 : 5 10 10 :- Cost: 10 + 10 = 20
Iteration 3 : 10 15 :- Cost: 20 + 15 = 35
Iteration 4 : 25 :- Cost: 35 + 25 = 60
public static int min_cost(int[] arr)
{
PriorityQueue<Integer> queue = new PriorityQueue<>();
//adding all the elements to the queue
for(Integer i : arr)
{
queue.offer(i);
}
int temp = 0;
int cost = 0;
while(queue.size() > 1)
{
// Removing the first two minimum elements from the queue
int first = queue.poll();
int second = queue.poll();
temp = first + second;
cost += temp;
//Adding back the sum of the minimum elements back to the queue
queue.offer(temp);
}
return cost;
}
参考: [1] https://www.journaldev.com/1642/java-priority-queue-priorityqueue-example