Number of subsets with product less than k

Last Updated : 11 Jul, 2025

Given an array arr[] of n elements. The task is to find the number of non-empty 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[] = [9, 8, 3], k = 2
Output: 0
Explanation: There are no subsets with products less than or equal to 2.

Try It Yourself
redirect icon

Using meet in middle approach - O(n*2n/2) time and O(2n/2) space

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 the array and store the value of the elements product for each subset separately into two containers (say subset1 & subset2). Then we combine the results of two halves to give a final answer. This technique is generally referred to as meet in the middle.

Algorithm:

  • Divide array into two equal parts.
  • Generate all subsets and for each subset calculate product of elements and store this to a container. Try this for both part of array.
  • Sort both container which contains products of elements for each possible subsets.
  • Traverse any one container and find upper-bound of element to find how many subsets are there 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 container(subset1 or subset2) if greater than k.
C++
// A C++ program to find the count subset having product
// less than k
#include <bits/stdc++.h>
using namespace std;

int numOfSubsets(vector<int> &arr, int k) {

    int n = arr.size();

    // declare four vector for dividing array into
    // two halves and storing product value of
    // possible subsets for them
    vector<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++) {
        int value = 1;
        for (int j = 0; j < vect1.size() and value <= k; 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++) {
        int value = 1;
        for (int j = 0; j < vect2.size() and value <= k; 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());

    int 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;
}

int main() {
    vector<int> arr = {4, 2, 3, 6, 5};
    int k = 25;
    cout << numOfSubsets(arr, k);
    return 0;
}
Java
// A java program to find the count subset having product
// less than k

import java.util.*;

class GfG {

    static int numOfSubsets(List<Integer> arr, int k) {
        int n = arr.size();

        // Declare four lists for dividing array into
        // two halves and storing product values of
        // possible subsets for them
        List<Integer> vect1 = new ArrayList<>();
        List<Integer> vect2 = new ArrayList<>();
        List<Integer> subset1 = new ArrayList<>();
        List<Integer> subset2 = new ArrayList<>();

        // Ignore elements greater than k and divide
        // array into 2 halves
        for (int i = 0; i < n; i++) {

            // Ignore element if greater than k
            if (arr.get(i) > k)
                continue;
            if (i <= n / 2)
                vect1.add(arr.get(i));
            else
                vect2.add(arr.get(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() && value <= k;
                 j++) {
                if ((i & (1 << j)) != 0)
                    value *= vect1.get(j);
            }

            // Add only if subset product is less than or
            // 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() && value <= k;
                 j++) {
                if ((i & (1 << j)) != 0)
                    value *= vect2.get(j);
            }

            // Add only if subset product is less than or
            // equal to k
            if (value <= k)
                subset2.add(value);
        }

        // Sort subset2
        Collections.sort(subset2);

        int count = 0;
        for (int s1 : subset1) {
            count += upperBound(subset2, k / s1);
        }

        // For null subset decrement 
      	// the value of count
        count--;

        return count;
    }

    // Helper function to find the upper bound index
    static int upperBound(List<Integer> list, int value) {
        int low = 0, high = list.size();
        while (low < high) {
            int mid = (low + high) / 2;
            if (list.get(mid) <= value) {
                low = mid + 1;
            }
            else {
                high = mid;
            }
        }
        return low;
    }

    public static void main(String[] args) {
        List<Integer> arr = Arrays.asList(4, 2, 3, 6, 5);
        int k = 25;
        System.out.println(numOfSubsets(arr, k));
    }
}
Python
# Python to find the count subset
# having product less than k

import bisect


def findSubset(arr, k):

    # declare four vector for dividing
    # array into two halves and storing
    # product value of possible subsets
    # for them
    n = len(arr)
    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

if __name__ == "__main__":

    arr = [4, 2, 3, 6, 5]
    k = 25
    print(findSubset(arr, k))
C#
// A C# program to find the count subset having product
// less than k

using System;
using System.Collections.Generic;

class GfG {

    // Function to find the count of subsets having product
    // less than k
    static int numOfSubsets(List<int> arr, int k) {

        int n = arr.Count;

        // Declare lists for dividing array into
        // two halves and storing product values 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 elements greater than k and divide
        // array into 2 halves
        for (int i = 0; i < n; i++) {
            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 && value <= k;
                 j++) {
                if ((i & (1 << j)) != 0)
                    value *= vect1[j];
            }

            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 && value <= k;
                 j++) {
                if ((i & (1 << j)) != 0)
                    value *= vect2[j];
            }

            if (value <= k)
                subset2.Add(value);
        }

        // Sort subset2
        subset2.Sort();

        int count = 0;
        foreach(int value in subset1) {
            count += BinarySearchUpperBound(subset2,
                                            k / value);
        }

        // For null subset decrement
      	// the value of count
        count--;

        return count;
    }

    // Binary search to find the upper bound of value in
    // subset2
    static int BinarySearchUpperBound(List<int> list,
                                             int value) {
        int low = 0, high = list.Count;
        while (low < high) {
            int mid = (low + high) / 2;
            if (list[mid] <= value)
                low = mid + 1;
            else
                high = mid;
        }
        return low;
    }

    static void Main(string[] args) {
        List<int> arr = new List<int>{ 4, 2, 3, 6, 5 };
        int k = 25;
        Console.WriteLine(numOfSubsets(arr, k));
    }
}
JavaScript
// A Javascript program to find the count subset having
// product less than k

function binarySearchUpperBound(arr, value) {
    let low = 0, high = arr.length;
    while (low < high) {
        let mid = Math.floor((low + high) / 2);
        if (arr[mid] <= value) {
            low = mid + 1;
        }
        else {
            high = mid;
        }
    }
    return low;
}

function numOfSubsets(arr, k) {
    let n = arr.length;

    // Declare lists for dividing array into
    // two halves and storing product values of
    // possible subsets for them
    let vect1 = [];
    let vect2 = [];
    let subset1 = [];
    let subset2 = [];

    // Ignore elements greater than k and divide
    // array into 2 halves
    for (let i = 0; i < n; i++) {
        if (arr[i] > k)
            continue;
        if (i <= Math.floor(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 && value <= k;
             j++) {
            if (i & (1 << j)) {
                value *= vect1[j];
            }
        }
        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 && value <= k;
             j++) {
            if (i & (1 << j)) {
                value *= vect2[j];
            }
        }
        if (value <= k) {
            subset2.push(value);
        }
    }

    // Sort subset2
    subset2.sort((a, b) => a - b);

    let count = 0;
    for (let value of subset1) {
        count += binarySearchUpperBound(
            subset2, Math.floor(k / value));
    }

    // For null subset decrement 
    // the value of count
    count--;

    return count;
}

const arr = [ 4, 2, 3, 6, 5 ];
const k = 25;
console.log(numOfSubsets(arr, k));

Output
15

Please refer to Number of subsets with product less than k using DP for Dynamic Programming solution.

Comment