Last Updated: 25 Feb, 2021

City of Happy People

Moderate
Asked in companies
Shell indiaD.E.ShawNXP Semiconductors

Problem statement

Ninja is traveling to a Happy city where ‘N’ people reside. In the city, the happiness of each person is represented as a number ‘H’ where ‘H’ ranges from -20,000,000 to 20,000,000 (both inclusive). The happiness of each person in the city is given in an array/list ‘HAPPINESS’ where ‘HAPPINESS[i]’ represents the happiness of the i’th person.

Ninja wants to make a group of people such that the overall happiness of the group (sum of happiness value of all the people in the group) ranges between ‘A’ and ‘B’ where -500,000,000 ≤ A ≤ B ≤ 500,000,000. Ninja wants to know in how many ways he can make this group.

For example :
For the given ‘HAPPINESS[]’ = ‘[-1, 0, 3]’ and ‘A’ = 0 , ‘B’ = 2. Following are the ways to group people such that the overall happiness of the group is between ‘A’ and ‘B’:

[-1, 0, 3], the sum of all the happiness values of this group is 2.

[-1, 3], the sum of all the happiness values of this group is 2.

[0], the sum of all the happiness values of this group is 0.

[ ], the sum of all the happiness values of this empty group is 0.

So the number of ways is 4.

As Ninja is busy with some other task so he asks you for help. Can you help Ninja to find out the number of ways in which he can pick groups so that the overall happiness of the group must be in the range between ‘A’ and ‘B’?

Input Format :
The first line of input contains an integer ‘T’ which denotes the number of test cases or queries to be run. Then the test cases follow.

The first line of each test case contains three single space-separated integers ‘N’, ’A’, and ‘B’ representing the number of elements in the array/list ‘HAPPINESS’ and the range in which happiness values of groups must reside respectively.

The next line of each test case contains ‘N’ single space-separated integers denoting the  ‘HAPPINESS’ values.
Output Format :
For each test case, print the number of ways to pick groups so that the overall happiness of the group lies between ‘A’ and ‘B’ inclusive.

Print the output of each test case in a separate line.
Note:
You do not need to print anything; it has already been taken care of. Just implement the given function.
Constraints :
1 <= ‘T’ <= 100
1 <= ‘N’ <= 34
-20,000,000 ≤ ‘HAPPINESS[i]’ ≤ 20,000,000
-500,000,000 ≤ ‘A’ ≤ ‘B’ ≤ 500,000,000

Time Limit: 1 second

Approaches

01 Approach

We know there are a total 2 ^ ‘N’ subsets possible for an array/list of ‘N’. elements. The idea behind this approach is to generate all possible subsets and then find the sum of all the happiness values in each subset. If this sum lies in between the range ‘A’ to ‘B’ (both inclusive) then include it in our final answer. 

 

Here is the complete algorithm:

 

  • Initialize a variable ‘answer’ that will be our final result.
  • Initialize a variable ‘sum’ = 0 and for each number ‘i’ from 0 to 2 ^ ‘N’, pick all array elements which corresponds to 1 in the binary representation of the ’i’ and add this element to the sum.
  • Check if the sum lies between ‘A’ to ‘B’ then add this to our ‘answer’.
  • Finally, return ‘answer’.

02 Approach

We can optimize the previous approach. In the brute force approach, there will be 2^34 (17179869184) subsets in the worst case. We can reduce this problem by dividing the ‘HAPPINESS’ into two sets [0…’N / 2’] and [‘N / 2’…’N - 1’] and find all subsets individually. 

 

Now we can find all the combinations of these sets giving the sum in the desired range. This can also be done in an optimized way, We need to sort one of the set ‘SET_A’ or ‘SET_B’ where as ‘SET_A’ contains subset sum of each subset from index 0 to ‘N’ / 2 of the ‘HAPPINESS’ and ‘SET_B’ contains subset sum of each subset from index ‘N’ / 2’ to ‘N’  of the ‘HAPPINESS’ .We will use binary search so that the values from one set that will turn out the sum for the particular value of the other set.

 

For Example: 

We have ‘N’ = 4, ‘A’ = -1 ,‘B’ = 1 and ‘HAPPINESS’ = [1, 2, -1, 0].

 

Set of all the subset sums of ‘HAPPINESS’ for 0 to ‘N’ / 2 is ‘SET_A’ and for ‘N’ / 2 to ‘N’ - 1 is ‘SET_B’.

 

We obtain these two sets like ‘SET_A’ = [0,1, 2, 3] and  ‘SET_B’ = [-1, -1, 0, 0] which contains all the possible happiness values. Now for each value in the 'SET_A' we will use the binary search algorithm for finding the values that would produce our desired sum using this approach we can get the total sets that yield the sum between 'A' and 'B'. 

 

Here is the complete algorithm:

 

  • Initialize a variable ‘answer’ = 0 to store the final result. We make two arrays/lists ‘left’ and ‘right’ to store the result of two halves  [0…’N / 2’] and [‘N / 2’…’N - 1’] of ‘HAPPINESS’. We will call our helper function ‘generateSubsets’ and store the resulting array/list in ‘left’ and ‘right’ respectively.
  • Here is the algorithm for ‘generateSubsets’ is:
    • Initialize a variable ‘sum’ = 0.
    • For ‘i’ = 0 to ‘i’ = 2 ^ ‘N’ do the following:
      • Iterate all the bits of ‘i’ and do the following:
        • If the bit is set then add that value to ‘sum’.
      • Finally, insert ‘sum’ into an array/list.
  • Sort the ‘right’ array/list in increasing order.
  • Iterate the ‘left’ array/list and for each element at index ‘i’ do the following:
    • Find out the position of the smallest element which is greater than or equal to ‘A’ - ‘left[i]’ using ‘lowerBound’ function and store it in a variable ‘low’.
    • Find out the position of the smallest element which is greater than ‘A’ - ‘left[i]’ using ‘upperBound’ and store it in a variable ‘high’.
    • Update ‘answer as  ‘answer’ = ‘answer’ + (‘high’-’right.begin()’)-(‘low’-’right.begin()’)
  • Finally, return ‘answer

 

Here is the algorithm for ‘lowerBound’ function:

 

  • This algorithm is used to find the position of the minimum element in a sorted array ‘HAPPINESS’ that is greater than or equal to ‘X
  • Initialize two variables ‘low’ = 0 and ‘high’ = ‘N’.Do the following while ‘low’ is less than ‘high’.
    • Initialize ‘mid’ = (‘low’ + ‘high’) / 2.
    • If ‘X’ <= ‘HAPPINES[mid]’ then ‘high’ = ‘mid’.
    • Else ‘low’ = ‘mid’ + 1.
  • Finally, return ‘low’.

 

Here is the algorithm for ‘upperBound’ function:

 

  • This algorithm is used to find the position of the minimum element in a sorted array ‘HAPPINESS’ that is greater than ‘X’.
  • Initialize two variables ‘low’ = 0 and ‘high’ = ‘N’.Do the following while ‘low’ is less than ‘high’.
    • Initialize ‘mid’ = (‘low’ + ‘high’) / 2.
    • If ‘X’ >= ‘HAPPINES[mid]’ then ‘low’ = ‘mid’ + 1.
    • Else ‘high’ = ‘mid’.
  • Finally, return ‘low’.