贪婪算法-减少完成任务的操作数

时间:2019-05-13 03:09:58

标签: algorithm greedy

我正在尝试解决编程挑战性问题。为了方便起见,我将其总结如下:

  

给出一个正整数数组A。在一个操作中,我们可以选择数组中元素的[strong>一个,即A [i]并将其减少固定数量X。与此同时,其余元素将减少a固定数量Y。我们需要找到最小操作数,以将所有元素减少到非正数(即0和以下)。

     

约束:
  1 <= | A | <= 1e5
  1 <= A [i] <= 1e9
  1 <= Y   时限:1秒

     

Source

例如,让X = 10,Y = 4和A = {20,20}。

此示例的最佳方法是:

操作1:选择项目0。

A = {10,16}

操作2:选择项目0。

A = {0,12}

操作3:选择项目1。

A = {-4,2}

操作4:选择项目1。

A = {-8,-8}

因此,答案是4。


我的方法:

继续选择数组中的 current 个最大元素,并将其减少X(将其余元素减少Y)。显然,由于X和Y的值可能较小(即我的算法将执行的迭代次数以max(A [i])/ 2为下限),因此该方法将超过时间限制。

有人可以建议我提供更好的解决方案吗?

1 个答案:

答案 0 :(得分:3)

可以通过使用二进制搜索解决此问题

首先,我们要检查是否在a操作中,是否可以使所有元素变为<= 0;我们可以检查每个元素的最小操作数b,这样,如果我们为x个操作减去b而为其余{{1}减去y }操作,则元素的结果值将变为<=0。将所有这些数字加在一起,如果使用a-b,则意味着可以使用sum <= a操作。

然后,我们可以应用二进制搜索来搜索有效的a

a

时间复杂度int st = 0; int ed = max element / y + 1; int result = ed; while(start <= end){ int mid = (st + ed)/2; int sum = 0; for(int i : A){ sum += minTimesMinusX(i, mid); } if(sum <= mid){ result = mid; ed = mid - 1; }else{ st = mid + 1; } } return result;