简体   繁体   中英

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.

Eg: consider an array[ 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.

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.

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. 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 .
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.

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 .

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

All possible subset is subset sum problem which is np hard . exponential which is 2**n .

I would propose the following solution:

Lets say the minimum value of range is minVal and maximum value is 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.

Search pass: I mean if number is at index i then number at index i+1 should be >=maxVal. Lets say the index of this number is currIndex. If this number is equal to maxVal then do binary search between 0 to currIndex for number

minVal and

Search Fail: This mean highest number is array is less than the maxVal. So for this case follow the steps below: 1) Add the largest number in array to the result set. 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. If arr[len-1] + arr[len] > maxVal then skip and check for 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
  2. Find all sets of size minVal
  3. As long as none of the sets meet your criteria, add 1 to minVal and go to step 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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