【问题标题】:What is a better solution than brute force for this?有什么比蛮力更好的解决方案呢?
【发布时间】:2019-02-08 12:45:37
【问题描述】:

给定一个介于 [0-5] 之间的有限正整数序列 假设 [0,3,1,5,2,4,4,4] 和起始序列 [0,0,0,0,0,0,0,0]。 我们现在想通过执行逐步操作从起始序列构建我们的给定序列。 在一个步骤中,我们可以将起始序列中的所有数字增加 1,或者仅将这个序列中的一个索引增加 1。 在这种情况下,一旦我们增加 5,它就会变成 0。

找到所需步骤最少的解决方案的最有效方法是什么?这个解决方案当然也应该适用于其他输入(长度+上限)。对于起始序列,我们可以假设每个索引始终为 0。

蛮力方法可能如下所示。

int upperBound = 5;
int[] endSequence = {0,3,1,5,2,4,4,4};
int currentBestSteps = Integer.MAX_VALUE;
int currentTimesIncreaseAll = 0;

for(int start = 0;start <= upperBound;start++){ //how many times to increase all
  //counter how many steps required total, starting with start amount of steps
  //since we increase all values 'start' times  
  int counterSteps = start; 

  //go through all end values and calc how many steps required  
  for(int end:endSequence){ 
    if(start <= end){
      counterSteps += end-start;
    }else{
      counterSteps += end+upperBound+1-start;
    }
  }

  System.out.println("solution: increase all "+start+
                     " times, total steps: "+counterSteps);

  if(counterSteps < currentBestSteps){
    currentBestSteps = counterSteps;
    currentTimesIncreaseAll = start;
  }
}
System.out.println("best solution: increase all "+currentTimesIncreaseAll+
                   " times, total steps: "+currentBestSteps);

结果:

solution: increase all 0 times, total steps: 23
solution: increase all 1 times, total steps: 22
solution: increase all 2 times, total steps: 21
solution: increase all 3 times, total steps: 20
solution: increase all 4 times, total steps: 19
solution: increase all 5 times, total steps: 30
best solution: increase all 4 times, total steps: 19

【问题讨论】:

  • 本案例的最佳解决方案是将所有索引增加 4 倍,当然,您必须继续单独增加每个索引!= 4。因此,例如,要为索引 1 获得 3,您需要 5 个步骤。总共需要 19 个步骤。
  • 我认为您只需要测试 increase-all 的数量作为列表中的唯一值之一,而不是从 0 到 upperBound 的所有值。在这里没有什么区别,但如果 upperBound 是一百万并且数组只有几百个元素,则可能很重要。

标签: algorithm performance brute-force


【解决方案1】:

我将提供一种方法来减少目标原始数组(称为A)以生成[0,0,0,0...],方法是减少所有内容或减少单个项目。这当然是同一个问题,但步骤相反。

首先,计算一个一个递减所有元素的成本。将此成本称为 CMAX 并将数组的长度称为 N。 CMAX = sum_for_all_i(A[i])

然后对数组进行排序,找到每个位置i i=0 或 A[i] > A[i-1] .

对于每个这样的位置,很容易计算将所有内容递减直到 A[i] 达到 0,然后 然后 逐个递减所产生的成本。这很容易,因为我们知道索引 处的所有内容都会环绕,而索引 >= i 处的所有内容都不会。所以:

COST(i) = CMAX + A[i] - A[i] * (N-i) + i*(UPPER_BOUND+1-A[i])

A[i] 是所有全局递减的成本。 - A[i] * (N-i) 是所有不环绕的高元素的成本降低,成本 i*(UPPER_BOUND+1-A[i] ) 是从 0 到 UPPER_BOUND 的所有元素增加的成本。

您找到的最低COST(包括CMAX)就是您的答案。总复杂度为 O(N log N),由排序决定。如果保证上限很小,那么您可以为此使用计数排序并获得 O(N+k)

【讨论】:

  • 想到了与此非常相似的东西,但没有来解决所有细节。不过,听起来似乎很合理。排序后,您只需要一些运行总和,然后遍历列表就足够了。
猜你喜欢
  • 2021-04-20
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 2013-10-22
  • 1970-01-01
相关资源
最近更新 更多