简体   繁体   English

给定一个大小的数组NI需要找到将在最小和最大范围内总和的最小值数

[英]Given an array of size N I need to find the min number of values that will sum up within a min and max range

Given an array of size NI need to find the min number of values that will sum up within a min and max range. 给定一个大小的数组NI需要找到将在最小和最大范围内总和的最小值数。

Eg: consider an array[ 1,2,3,4,5 ]. 例如:考虑一个数组[1,2,3,4,5]。 I need to find min number of values from this array whose sum is greater than 5 and less than 8. Ans: since 1+5 is greater than 5 and less than 8 so the min number of values is 2 hence the answer. 我需要从这个数组中找到最小数量的值,其总和大于5且小于8. Ans:因为1 + 5大于5且小于8所以最小值数为2因此答案。

And below is my function which implements the logic. 下面是我实现逻辑的函数。

int void CheckValue()
{
 for (i = 0; i <5; i++)
    if (a[i] > min && a[i] < max)
       return 1;
 for (i = 0; i< 4; i++)
     for (j = i + 1; j < 5; j++)
         if (a[i] + a[j] > min && a[i] + a[j] < max)
            return 2;


  for (i = 0; i < 3; i++)
      for (j = i + 1; j < 4; j++)
          for (k = j+1; k < 5; k++)
              if (a[i] + a[j] + a[k] > min && a[i] + a[j] + a[k] < max) 
                 return 3;
  for (i = 0; i < 2; i++)
      for (j = i + 1; j< 3; j++)
          for (k = j + 1; k< 4; k++)
              for (l = k + 1; l < 5; l++)
                  if (a[i] + a[j] + a[k] + a[l] > min && a[i] + a[j] + a[k] + a[l] < max)
                     return 4;
  if(a[0]+a[1]+a[2]+a[3]+a[4]>min && a[0]+a[1]+a[2]+a[3]+a[4]<max)
         return 5;
  return 0;
 }

It works fine but the problem is its complexity. 它工作正常,但问题是它的复杂性。 Can anyone provide any suggestions to optimize this code further or provide a better logic to implement this. 任何人都可以提供任何建议来进一步优化此代码或提供更好的逻辑来实现它。

I don't have any experience with this kind of things so it is probable that there are better ways of doing it, but I do have some insights that may be helpful. 我对这类事情没有任何经验,所以很可能有更好的方法,但我确实有一些可能有用的见解。

Currently you are calculating every possible combination, you should be able to alter your algorithm to make it so that you can eliminate some combinations without having to calculate them. 目前您正在计算每种可能的组合,您应该能够改变算法以使其能够消除某些组合,而无需计算它们。

I would sort the array to begin with, that will let you eliminate some values without calculating them. 我会先对数组进行排序,这样可以在不计算数值的情况下消除某些值。

For instance if you have an array that looks like [1,2,4,5,9] and the min=11 and max=14 then your algorithm will check 1+2,1+4,1+5,1+9 then 2+4, 2+5, 2+9, 4+5, 4+9 before coming to an answer. 例如,如果你有一个看起来像[1,2,4,5,9]和min = 11和max = 14的数组,那么你的算法将检查1 + 2,1 + 4,1 + 5,1 + 9然后2 + 4,2 + 5,2 + 9,4 + 5,4 + 9才得到答案。

If instead you start with the highest number first you can eliminate all possible 1 combinations by doing the calculation 9+1, since 9+1<=11 it must be the case that all other possible 1 combinations are invalid for the two number sum, the same with all possible 2 combinations. 如果你首先从最高的数字开始,你可以通过计算9 + 1来消除所有可能的1个组合,因为9 + 1 <= 11必须是所有其他可能的1个组合对于两个数字总和无效的情况,与所有可能的2种组合相同。 If you add logic like this to your code you should have less superfluous calculations, hopefully speeding your code up. 如果你在代码中添加这样的逻辑,你应该有更少的多余计算,希望能加速你的代码。

Is this a homework question? 这是一个功课问题吗?

Your question is really not clear but here is what i would : 你的问题真的不明确,但我会这样:

Sort it. 解决。 nlogn . nlogn
Start with adding the first element and last element. 首先添加第一个元素和最后一个元素。 Is that in the range? 那是在范围内吗? Take the first pointer from one end, lets say from beginning, move it to middle and add the middle number and the last number, first pointer + last pointer. 从一端拿出第一个指针,从开头开始,将其移动到中间并添加中间数字和最后一个数字,第一个指针+最后一个指针。 is that in the range? 是在范围内? you can move the first pointer to the middle between first and last pointer, ie: right by 3/4 of the sequence. 你可以将第一个指针移动到第一个和最后一个指针之间的中间位置,即:右边是序列的3/4。

So you are using binary search here with two pointers on a sorted sequence. 所以你在这里使用二进制搜索,在排序的序列上有两个指针。

This will give you an estimate number of elements, which will be in range. 这将为您提供估计的元素数量,这些元素将在范围内。 I hope you got the idea. 我希望你有这个主意。

You can move the second pointer to middle, if your sum is out of range. 如果总和超出范围,则可以将第二个指针移动到中间。

This will give you nlogn . 这将给你nlogn

Please note that this is just for two numbers, im not sure if you are asking for all possible numbers whose addition would be in the range or only two numbers? 请注意,这仅适用于两个数字,我不确定您是否要求所有可能的数字添加在范围内或只有两个数字?

two numbers is easy, nlogn does it 两个数字很容易, nlogn做到了

All possible subset is subset sum problem which is np hard . 所有可能的子集都是np难的子集和问题。 exponential which is 2**n . 指数,即2 ** n

I would propose the following solution: 我建议以下解决方案:

Lets say the minimum value of range is minVal and maximum value is maxVal. 假设范围的最小值是minVal,最大值是maxVal。 Now sort the array.Lets say the length of array is len Do a binary search for number in array which is just <= maxVal. 现在对数组进行排序。让我们说数组的长度是len对数组中的数字进行二进制搜索只是<= maxVal。

Search pass: I mean if number is at index i then number at index i+1 should be >=maxVal. 搜索传递:我的意思是如果数字在索引i处,那么索引i + 1处的数字应该> = maxVal。 Lets say the index of this number is currIndex. 让我们说这个数字的索引是currIndex。 If this number is equal to maxVal then do binary search between 0 to currIndex for number 如果此数字等于maxVal,则在0到currIndex之间进行二进制搜索以获取数字

minVal and minVal和

Search Fail: This mean highest number is array is less than the maxVal. 搜索失败:这意味着最大数字是数组小于maxVal。 So for this case follow the steps below: 1) Add the largest number in array to the result set. 因此,对于这种情况,请按照以下步骤操作:1)将数组中的最大数字添加到结果集中。 2)Now start loop from len-1 t0 1. if arr[len-1] + arr[len] is less that maxVal then add arr[len-1] to result set and continue the loop. 2)现在从len-1 t0开始循环1.如果arr [len-1] + arr [len]小于maxVal,则将arr [len-1]添加到结果集并继续循环。 If arr[len-1] + arr[len] > maxVal then skip and check for arr[len-1] + arr[len]. 如果arr [len-1] + arr [len]> maxVal,则跳过并检查arr [len-1] + arr [len]。

and so on. 等等。

This is a rather complex problem, likely to be np hard. 这是一个相当复杂的问题,可能很难。

One thing that comes to mind is that it slightly resembles the 'knapsack problem'. 我想到的一件事是,它有点类似于“背包问题”。 Perhaps you can find an implementation of that and adapt it. 也许你可以找到它的实现并进行调整。


If the minimum amount of items is expected to be small, you can of course use a brute force approach: 如果预计最小数量的项目很小,您当然可以使用蛮力方法:

  1. Set minVal = 1 设置minVal = 1
  2. Find all sets of size minVal 找到所有尺寸minVal的集合
  3. As long as none of the sets meet your criteria, add 1 to minVal and go to step 2 只要没有一组符合您的标准,请将1添加到minVal并转到步骤2

I think you should consider sorting your array, there are many efficient algoritms for this. 我认为你应该考虑对数组进行排序,有很多有效的算法。

Then start from the biggest value and cummulatively add smaller values in sorted order, checking the condition at each step. 然后从最大值开始并按排序顺序累加较小值,检查每一步的条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM