 Open in App
Not now

# Number of subsets with product less than k

• Difficulty Level : Hard
• Last Updated : 24 Jan, 2023

You are given an array of n-elements, you have to find the number of subsets whose product of elements is less than or equal to a given integer k.

Examples:

```Input : arr[] = {2, 4, 5, 3}, k = 12
Output : 8
Explanation : All possible subsets whose
products are less than 12 are:
(2), (4), (5), (3), (2, 4), (2, 5), (2, 3), (4, 3)

Input : arr[] = {12, 32, 21 }, k = 1
Output : 0
Explanation : there is not any subset such
that product of elements is less than 1```

Approach : If we go through the basic approach to solve this problem, then we have to generate all possible 2n subset and for each of then we have to calculate product of elements of subset and compare products value with given then. But the disadvantage of this approach is that its time complexity is too high i.e. O(n*2n). Now, we can see that it is going to be exponential time complexity which should be avoided in case of competitive codings.

Advance Approach : We are going to use the concept of meet in the middle. By, using this concept we can reduce the complexity of our approach to O(n*2n/2)

How to use MEET IN THE MIDDLE Approach :

First of all we simply divide the given array into two equal parts and after that we generate all possible subsets for both parts of array and store value of elements product for each subset separately into two vectors (say subset1 & subset2). Now this will cost O(2n/2) time complexity.

Now if we sort these two vectors(subset1 & subset2) having (2n/2) elements each then this will cost O(2n/2*log2n/2) ≈ O(n*(2n/2)) Time complexity. In next step we traverse one vector subset1 with 2n/2 elements and find the upper bound of k/subset1[i] in second vector which will tell us the count of total elements whose products will be less than or equal to k. And thus for each element in subset1 we will try to perform a binary search in form of upper_bound in subset2 resulting again a Time complexity of O(n*(2n/2)).

So, if we try to compute our overall complexity for this approach we will have O(n*(2n/2) + n*(2n/2) + n*(2n/2)) ≈ O(n*(2n/2)) as our time complexity which is much efficient than our brute force approach.

Algorithm :

1. Divide array into two equal parts.
2. Generate all subsets and for each subset calculate product of elements and push this to a vector. try this for both part of array.
3. Sort both new vector which contains products of elements for each possible subsets.
4. Traverse any one vector and find upper-bound of element k/vector[i] to find how many subsets are there for vector[i] whose product of elements is less than k.

Some key points to improve complexity :

• Ignore elements from array if greater than k.
• Ignore product of elements to push into vector (subset1 or subset2) if greater than k.

Below is the implementation of the above approach:

## C++

 `// CPP to find the count subset having product` `// less than k` `#include ` `using` `namespace` `std;`   `int` `findSubset(``long` `long` `int` `arr[], ``int` `n,` `               ``long` `long` `int` `k)` `{` `    ``// declare four vector for dividing array into` `    ``// two halves and storing product value of` `    ``// possible subsets for them` `    ``vector<``long` `long` `int``> vect1, vect2, subset1, subset2;`   `    ``// ignore element greater than k and divide` `    ``// array into 2 halves` `    ``for` `(``int` `i = 0; i < n; i++) {`   `        ``// ignore element if greater than k` `        ``if` `(arr[i] > k)` `            ``continue``;` `        ``if` `(i <= n / 2)` `            ``vect1.push_back(arr[i]);` `        ``else` `            ``vect2.push_back(arr[i]);` `    ``}`   `    ``// generate all subsets for 1st half (vect1)` `    ``for` `(``int` `i = 0; i < (1 << vect1.size()); i++) {` `        ``long` `long` `value = 1;` `        ``for` `(``int` `j = 0; j < vect1.size(); j++) {` `            ``if` `(i & (1 << j))` `                ``value *= vect1[j];` `        ``}`   `        ``// push only in case subset product is less` `        ``// than equal to k` `        ``if` `(value <= k)` `            ``subset1.push_back(value);` `    ``}`   `    ``// generate all subsets for 2nd half (vect2)` `    ``for` `(``int` `i = 0; i < (1 << vect2.size()); i++) {` `        ``long` `long` `value = 1;` `        ``for` `(``int` `j = 0; j < vect2.size(); j++) {` `            ``if` `(i & (1 << j))` `                ``value *= vect2[j];` `        ``}`   `        ``// push only in case subset product is` `        ``// less than equal to k` `        ``if` `(value <= k)` `            ``subset2.push_back(value);` `    ``}`   `    ``// sort subset2` `    ``sort(subset2.begin(), subset2.end());`   `    ``long` `long` `count = 0;` `    ``for` `(``int` `i = 0; i < subset1.size(); i++)` `        ``count += upper_bound(subset2.begin(), subset2.end(),` `                             ``(k / subset1[i]))` `                 ``- subset2.begin();`   `    ``// for null subset decrement the value of count` `    ``count--;`   `    ``// return count` `    ``return` `count;` `}`   `// driver program` `int` `main()` `{` `    ``long` `long` `int` `arr[] = { 4, 2, 3, 6, 5 };` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr);` `    ``long` `long` `int` `k = 25;` `    ``cout << findSubset(arr, n, k);` `    ``return` `0;` `}`

## Java

 `// Java to find the count subset having product less than k`   `import` `java.io.*;` `import` `java.util.*;`   `class` `GFG {`   `    ``static` `int` `upper_bound(List arr, ``int` `key)` `    ``{` `        ``int` `upperBound = ``0``;` `        ``while` `(upperBound < arr.size()) {` `            ``if` `(arr.get(upperBound) <= key) {` `                ``upperBound++;` `            ``}` `            ``else` `{` `                ``return` `arr.get(upperBound);` `            ``}` `        ``}` `        ``return` `-``1``;` `    ``}`   `    ``static` `int` `findSubset(``int``[] arr, ``int` `n, ``int` `k)` `    ``{` `        ``// declare four vector for dividing array into two` `        ``// halves and storing product value of possible` `        ``// subsets for them` `        ``List vect1 = ``new` `ArrayList<>();` `        ``List vect2 = ``new` `ArrayList<>();` `        ``List subset1 = ``new` `ArrayList<>();` `        ``List subset2 = ``new` `ArrayList<>();`   `        ``// ignore element greater than k and divide array` `        ``// into 2 halves` `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``// ignore element if greater than k` `            ``if` `(arr[i] > k) {` `                ``continue``;` `            ``}` `            ``if` `(i <= n / ``2``) {` `                ``vect1.add(arr[i]);` `            ``}` `            ``else` `{` `                ``vect2.add(arr[i]);` `            ``}` `        ``}`   `        ``// generate all subsets for 1st half (vect1)` `        ``for` `(``int` `i = ``0``; i < (``1` `<< vect1.size()); i++) {` `            ``int` `value = ``1``;` `            ``for` `(``int` `j = ``0``; j < vect1.size(); j++) {` `                ``if` `((i & (``1` `<< j)) != ``0``) {` `                    ``value *= vect1.get(j);` `                ``}` `            ``}` `            ``// push only in case subset product is less than` `            ``// equal to k` `            ``if` `(value <= k) {` `                ``subset1.add(value);` `            ``}` `        ``}`   `        ``// generate all subsets for 2nd half (vect2)` `        ``for` `(``int` `i = ``0``; i < (``1` `<< vect2.size()); i++) {` `            ``int` `value = ``1``;` `            ``for` `(``int` `j = ``0``; j < vect2.size(); j++) {` `                ``if` `((i & (``1` `<< j)) != ``0``) {` `                    ``value *= vect2.get(j);` `                ``}` `            ``}` `            ``// push only in case subset product is less than` `            ``// equal to k` `            ``if` `(value <= k) {` `                ``subset2.add(value);` `            ``}` `        ``}`   `        ``// sort subset2` `        ``Collections.sort(subset2);`   `        ``int` `count = ``0``;` `        ``for` `(``int` `i = ``0``; i < subset1.size(); i++) {` `            ``count += upper_bound(subset2,` `                                 ``(k / subset1.get(i)));` `        ``}` `        ``// for null subset decrement the value of count` `        ``count--;`   `        ``// return count` `        ``return` `count;` `    ``}`   `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int``[] arr = { ``4``, ``2``, ``3``, ``6``, ``5` `};` `        ``int` `n = arr.length;` `        ``int` `k = ``25``;` `        ``System.out.print(findSubset(arr, n, k));` `    ``}` `}`   `// This code is contributed by lokeshmvs21.`

## Python3

 `# Python3 to find the count subset ` `# having product less than k ` `import` `bisect`   `def` `findSubset(arr, n, k): `   `    ``# declare four vector for dividing ` `    ``# array into two halves and storing ` `    ``# product value of possible subsets` `    ``# for them ` `    ``vect1, vect2, subset1, subset2 ``=` `[], [], [], [] `   `    ``# ignore element greater than k and ` `    ``# divide array into 2 halves ` `    ``for` `i ``in` `range``(``0``, n): `   `        ``# ignore element if greater than k ` `        ``if` `arr[i] > k: ` `            ``continue` `        ``if` `i <``=` `n ``/``/` `2``: ` `            ``vect1.append(arr[i]) ` `        ``else``:` `            ``vect2.append(arr[i]) `   `    ``# generate all subsets for 1st half (vect1) ` `    ``for` `i ``in` `range``(``0``, (``1` `<< ``len``(vect1))): ` `        ``value ``=` `1` `        ``for` `j ``in` `range``(``0``, ``len``(vect1)): ` `            ``if` `i & (``1` `<< j): ` `                ``value ``*``=` `vect1[j] `   `        ``# push only in case subset product ` `        ``# is less than equal to k ` `        ``if` `value <``=` `k:` `            ``subset1.append(value) `   `    ``# generate all subsets for 2nd half (vect2) ` `    ``for` `i ``in` `range``(``0``, (``1` `<< ``len``(vect2))): ` `        ``value ``=` `1` `        ``for` `j ``in` `range``(``0``, ``len``(vect2)): ` `            ``if` `i & (``1` `<< j): ` `                ``value ``*``=` `vect2[j] `   `        ``# push only in case subset product ` `        ``# is less than equal to k ` `        ``if` `value <``=` `k:` `            ``subset2.append(value) `   `    ``# sort subset2 ` `    ``subset2.sort() `   `    ``count ``=` `0` `    ``for` `i ``in` `range``(``0``, ``len``(subset1)): ` `        ``count ``+``=` `bisect.bisect(subset2, (k ``/``/` `subset1[i]))`   `    ``# for null subset decrement the ` `    ``# value of count ` `    ``count ``-``=` `1`   `    ``# return count ` `    ``return` `count `   `# Driver Code` `if` `__name__ ``=``=` `"__main__"``: `   `    ``arr ``=` `[``4``, ``2``, ``3``, ``6``, ``5``] ` `    ``n ``=` `len``(arr) ` `    ``k ``=` `25` `    ``print``(findSubset(arr, n, k)) `   `# This code is contributed by Rituraj Jain`

## C#

 `// C# to find the count subset having product less than k`   `using` `System;` `using` `System.Collections;` `using` `System.Collections.Generic;`   `class` `GFG {`   `  ``static` `int` `upper_bound(List<``int``> arr, ``int` `key)` `  ``{` `    ``int` `upperBound = 0;` `    ``while` `(upperBound < arr.Count) {` `      ``if` `(arr[upperBound] <= key) {` `        ``upperBound++;` `      ``}` `      ``else` `{` `        ``return` `arr[upperBound];` `      ``}` `    ``}` `    ``return` `-1;` `  ``}`   `  ``static` `int` `findSubset(``int``[] arr, ``int` `n, ``int` `k)` `  ``{` `    ``// declare four vector for dividing array into two` `    ``// halves and storing product value of possible` `    ``// subsets for them` `    ``List<``int``> vect1 = ``new` `List<``int``>();` `    ``List<``int``> vect2 = ``new` `List<``int``>();` `    ``List<``int``> subset1 = ``new` `List<``int``>();` `    ``List<``int``> subset2 = ``new` `List<``int``>();`   `    ``// ignore element greater than k and divide array` `    ``// into 2 halves` `    ``for` `(``int` `i = 0; i < n; i++) {` `      ``// ignore element if greater than k` `      ``if` `(arr[i] > k) {` `        ``continue``;` `      ``}` `      ``if` `(i <= n / 2) {` `        ``vect1.Add(arr[i]);` `      ``}` `      ``else` `{` `        ``vect2.Add(arr[i]);` `      ``}` `    ``}`   `    ``// generate all subsets for 1st half (vect1)` `    ``for` `(``int` `i = 0; i < (1 << vect1.Count); i++) {` `      ``int` `value = 1;` `      ``for` `(``int` `j = 0; j < vect1.Count; j++) {` `        ``if` `((i & (1 << j)) != 0) {` `          ``value *= vect1[j];` `        ``}` `      ``}` `      ``// push only in case subset product is less than` `      ``// equal to k` `      ``if` `(value <= k) {` `        ``subset1.Add(value);` `      ``}` `    ``}`   `    ``// generate all subsets for 2nd half (vect2)` `    ``for` `(``int` `i = 0; i < (1 << vect2.Count); i++) {` `      ``int` `value = 1;` `      ``for` `(``int` `j = 0; j < vect2.Count; j++) {` `        ``if` `((i & (1 << j)) != 0) {` `          ``value *= vect2[j];` `        ``}` `      ``}` `      ``// push only in case subset product is less than` `      ``// equal to k` `      ``if` `(value <= k) {` `        ``subset2.Add(value);` `      ``}` `    ``}`   `    ``// sort subset2` `    ``subset2.Sort();`   `    ``int` `count = 0;` `    ``for` `(``int` `i = 0; i < subset1.Count; i++) {` `      ``count += upper_bound(subset2, (k / subset1[i]));` `    ``}` `    ``// for null subset decrement the value of count` `    ``count--;`   `    ``// return count` `    ``return` `count;` `  ``}`   `  ``public` `static` `void` `Main(``string``[] args)` `  ``{` `    ``int``[] arr = { 4, 2, 3, 6, 5 };` `    ``int` `n = arr.Length;` `    ``int` `k = 25;` `    ``Console.Write(findSubset(arr, n, k));` `  ``}` `}`   `// This code is contributed by karandeep1234.`

## Javascript

 `// JavaScript to find the count subset ` `// having product less than k` `function` `upper_bound(arr, key) {` `    ``let upperBound = 0;` `    ``while` `(upperBound < arr.length) {` `        ``if` `(arr[upperBound] <= key) {` `        ``upperBound++;` `        ``} ``else` `{` `            ``return` `arr[upperBound];` `        ``}` `    ``}` `    ``return` `-1;` `}`   `function` `findSubset(arr, n, k)` `{`   `    ``// declare four vector for dividing ` `    ``// array into two halves and storing ` `    ``// product value of possible subsets ` `    ``// for them` `    ``let vect1 = [];` `    ``let vect2 = [];` `    ``let subset1 = [];` `    ``let subset2 = [];`   `    ``// ignore element greater than k ` `    ``// and divide array into 2 halves` `    ``for` `(let i = 0; i < n; i++)` `    ``{` `    `  `        ``// ignore element if greater than k` `        ``if` `(arr[i] > k) {` `            ``continue``;` `        ``}` `        ``if` `(i <= n / 2) {` `            ``vect1.push(arr[i]);` `        ``} ``else` `{` `            ``vect2.push(arr[i]);` `        ``}` `    ``}`   `    ``// generate all subsets for 1st half (vect1)` `    ``for` `(let i = 0; i < (1 << vect1.length); i++) {` `        ``let value = 1;` `        ``for` `(let j = 0; j < vect1.length; j++) {` `            ``if` `((i & (1 << j)) !== 0) {` `                ``value *= vect1[j];` `            ``}` `        ``}` `        `  `        ``// push only in case subset product ` `        ``// is less than equal to k` `        ``if` `(value <= k) {` `            ``subset1.push(value);` `        ``}` `    ``}`   `    ``// generate all subsets for 2nd half (vect2)` `    ``for` `(let i = 0; i < (1 << vect2.length); i++) {` `        ``let value = 1;` `        ``for` `(let j = 0; j < vect2.length; j++) {` `            ``if` `((i & (1 << j)) !== 0) {` `                ``value *= vect2[j];` `            ``}` `        ``}` `        ``// push only in case subset product ` `        ``// is less than equal to k` `        ``if` `(value <= k) {` `            ``subset2.push(value);` `        ``}` `    ``}`   `    ``// sort subset2` `    ``subset2.sort(``function``(a, b) {` `    ``return` `a - b;` `    ``});`   `    ``let count = 0;` `    ``for` `(let i = 0; i < subset1.length; i++) {` `        ``count += upper_bound(subset2, k / subset1[i]);` `    ``}` `    `  `    ``// for null subset decrement the value of count` `    ``count--;`   `    ``// return count` `    ``return` `count;` `}`   `let arr = [4, 2, 3, 6, 5];` `let n = arr.length;` `let k = 25;` `console.log(findSubset(arr, n, k));`   `// This code is contributed by lokesh.`

Output

`15`

My Personal Notes arrow_drop_up
Related Articles