动态编程 - 固定大小的固定数组

时间:2015-01-29 10:18:33

标签: arrays algorithm dynamic dynamic-programming

这是我遇到的问题:

  

给出两个整数:N(数组的大小)和S(数组所有元素的所需总和)

     

要求是构造一个大小为N的数组,并使用其元素S的总和,使得:

     
      
  • 数组包含N 正非零值

  •   
  • 向量的元素是不同的

  •   
  • 数组中最大和最小元素之间的绝对差异是

  •   
  • 如果有超过1个绝对差值相等的解,则会显示最小词典解法。

  •   

我无法真正解决如何解决问题的方法。任何帮助都很可爱。

2 个答案:

答案 0 :(得分:2)

我认为可以通过施工来实现。

取N = 6且S = 30

1)像这样初始化你的数组:{1,2,3,4,5,6}

2)从最新到第一个循环和递增:

{1,2,3,4,5,6} S = 21
{1,2,3,4,5,7} S = 22
{1,2,3,4,6,7} S = 23
{1,2,3,5,6,7} S = 24
{1,2,4,5,6,7} S = 25
{1,3,4,5,6,7} S = 26
{2,3,4,5,6,7} S = 27

再次循环:

{2,3,4,5,6,7} S = 27
{2,3,4,5,6,8} S = 28
{2,3,4,5,7,8} S = 29
{2,3,4,6,7,8} S = 30

也许有一个公式可以找到一个好的开始。例如,您可以从:

开始
 {S/N - N, S/N - N+1, S/N - N+2, ...}

答案 1 :(得分:2)

前N个正值{1,2,3 ... N)之和为(N + 1)*N/2

因此,我们可以很容易地得出N个连续正数之和的公式(从a开始)

((N + a - 1) + a)*N/2 = (N + 2*a - 1)*N/2

使用 二元搜索 ,我们可以找到最大起始数a 的N个连续数字,其总和<= S。

所以让dif = S - (N + 2*a - 1)*N/2 - &gt;所以最后的dif数应加1,其余N - dif数字为N - dif + a, ..., a

伪代码

int start = 1;
int end = S;
int result = 1;
while(start <= end){
    int mid = (start + end)/2;
    int sum = sum(mid);   
    if(sum <= S){
       result = max(mid,result); 
       start = mid + 1;
    }else{
       end = mid - 1;
    } 
}
//So we know that the sequence starting at result
//Now we need to find the diff
int dif = S - sum(result);

for(int i = 0; i < N; i++){
   if(i >= N - dif ){//last N - dif number is added one
      print (i + result + 1);

   }else{
      print (i + result);
   }
}

int sum(int a){//Return sum from a to N + a - 1
    return (N +2*a - 1)*N/2     
}
相关问题