通过添加元素来减少数组

时间:2016-12-06 09:36:33

标签: algorithm

我在测试中遇到了这个问题。

给定一个数组,以最低的成本将数组减少为单个元素。要减少,请从数组中删除两个元素,添加这两个数字并将总和保留在数组中。每项操作的成本是该步骤中删除的元素的总和。

示例,让数组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)

这可能是一个有效的算法吗?

7 个答案:

答案 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