Open In App

Number of subarrays with given product

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of positive numbers and a number k, find the number of subarrays having product exactly equal to k. We may assume that there is no overflow.

Examples : 

Input : arr = [2, 1, 1, 1, 4, 5]
        k = 4
Output : 4
1st subarray : arr[1..4]
2nd subarray : arr[2..4]
3rd subarray : arr[3..4]
4th subarray : arr[4]

Input : arr = [1, 2, 3, 4, 1]
        k = 24
Output : 4
1st subarray : arr[0..4]
2nd subarray : arr[1..4]
3rd subarray : arr[1..3]
4th subarray : arr[0..3]

A simple solution is to consider all subarrays and find their products. For every product, check if it is equal to k. If yes, then increment result.

An efficient solution is to use sliding window technique can be used to solve the problem. We use two pointers start and end to represent starting and ending point of sliding window.
Initially both start and end point to the beginning of the array, i.e. index 0. Keep incrementing end until product p < k. As soon as p becomes equal to k stop incrementing end and check whether the current position of end is followed by a series of 1s in the array. If yes then those 1s will also contribute to the subarray count. Store the count of these succeeding 1s in a variable countOnes. After this keep incrementing start until p equals to k while adding (countOnes + 1) to result. If start coincides with end then again start from incrementing end and follow the same procedure. Do this until end < array size.

Why countOnes + 1 is added to result? 
Consider the second test case in the above sample cases. If we follow the above mentioned procedure, then after incrementing end, we will reach at start = 0 and end = 3. After this the countOnes is set equal to 1. How many subarrays are there for start = 0 ? There are two subarrays : arr[0..3] and arr[0..4]. Observe that subarray[0..3] is what we have found using sliding window technique. This increases the result count by 1 and is what represented by + 1 in expression countOnes + 1. The other subarray[0..4] is simply obtained by appending single 1 to the subarray[0..3], i.e. adding countOnes number of 1s one at a time. Let us try to generalise it. Suppose arr[0..i] is the subarray obtained using sliding window technique and let countOnes = j. Then we can expand this subarray by unit length at a time by appending single 1 to this subarray. After appending a single 1 to arr[0..i] the new subarray is arr[0..i+1] and result is also increased by 1. countOnes now decrease by 1 and equals j – 1. We can continuously append single 1 at a time and obtain a new subarray until countOnes is not equal to zero. 

Thus the result count increases by countOnes and is represented as countOnes in expression countOnes + 1. So for every increment in start until p equals k simply add countOnes + 1 to the result. 

Note that above algorithm will not work for the case when k = 1. e.g. Consider the test case arr[] = {2, 1, 1, 1}. Thanks to Jeel Santoki for this test case. For the case when k = 1, we will find length of each segment of array in which all elements are 1. Let the length of particular segment of 1 is x. The number of subarrays of this segment will be x*(x+1)/2. All these subarrays will have product 1 as all elements are 1. In given test case there is only one segment of 1 from index 1 to index 3 having length 3. So total subarrays with product 1 are (3*4)/2 = 6. 

The algorithm can be listed as: 

For k != 1:
1. Initialize start = end = 0
2. Initialize res = 0, p = 1 
3. Increment end until p < k
4. When p = k do:
     Set countOnes = number of succeeding ones
     res += (countOnes+1)
     Increment start until p = k
     and do res += (countOnes+1)
5. Stop if end = n

For k = 1:
1. Find all segments in array in which 
   only 1 is present.
2. Find length of each segment.
3. Add length*(length+1) / 2 to result.

Implementation: 

C++




// C++ program to find number of subarrays
// having product exactly equal to k.
#include <bits/stdc++.h>
using namespace std;
 
// Function to find number of subarrays
// having product equal to 1.
int countOne(int arr[], int n){
    int i = 0;
     
    // To store number of ones in
    // current segment of all 1s.
    int len = 0;
     
    // To store number of subarrays
    // having product equal to 1.
    int ans = 0;
     
    while(i < n){
         
        // If current element is 1, then
        // find length of segment of 1s
        // starting from current element.
        if(arr[i] == 1){
            len = 0;
            while(i < n && arr[i] == 1){
                i++;
                len++;
            }
             
            // add number of possible
            // subarrays of 1 to result.
            ans += (len*(len+1)) / 2;
        }
        i++;
    }
     
    return ans;
}
 
/// Function to find number of subarrays having
/// product exactly equal to k.
int findSubarrayCount(int arr[], int n, int k)
{
    int start = 0, endval = 0, p = 1,
        countOnes = 0, res = 0;
 
    while (endval < n)
    {
        p *= (arr[endval]);
 
        // If product is greater than k then we need to decrease
        // it. This could be done by shifting starting point of
        // sliding window one place to right at a time and update
        // product accordingly.
        if(p > k)
        {
            while(start <= endval && p > k)
            {
                p /= arr[start];
                start++;
            }
        }
         
         
        if(p == k)
        {
            // Count number of succeeding ones.
            countOnes = 0;
            while(endval + 1 < n && arr[endval + 1] == 1)
            {
                countOnes++;
                endval++;
            }
 
            // Update result by adding both new subarray
            // and effect of succeeding ones.
            res += (countOnes + 1);
 
            // Update sliding window and result according
            // to change in sliding window. Here preceding
            // 1s have same effect on subarray as succeeding
            // 1s, so simply add.
            while(start <= endval && arr[start] == 1 && k!=1)
            {
                res += (countOnes + 1);
                start++;
            }
 
            // Move start to correct position to find new
            // subarray and update product accordingly.
            p /= arr[start];
            start++;
        }
 
        endval++;
    }
    return res;
}
 
// Driver code
int main()
{
    int arr1[] = { 2, 1, 1, 1, 3, 1, 1, 4};
    int n1 = sizeof(arr1) / sizeof(arr1[0]);
    int k = 1;
     
    if(k != 1)
        cout << findSubarrayCount(arr1, n1, k) << "\n";
    else
        cout << countOne(arr1, n1) << "\n";
     
    int arr2[] = { 2, 1, 1, 1, 4, 5};
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    k = 4;
     
    if(k != 1)
        cout << findSubarrayCount(arr2, n2, k) << "\n";
    else
        cout << countOne(arr2, n2) << "\n";
    return 0;
}


Java




// Java program to find number of subarrays
// having product exactly equal to k.
import java.util.*;
 
class GFG
{
    // Function to find number of subarrays having
    // product exactly equal to k.
    public static int findSubarrayCount(int arr[], int n, int k)
    {
        int start = 0, endval = 0;
        int p = 1, countOnes = 0, res = 0;
        while(endval < n)
        {
            p *= (arr[endval]);
             
            // If product is greater than k then we need
            // to decrease it. This could be done by shifting
            // starting point of sliding window one place
            // to right at a time and update product accordingly.
            if (p > k)
            {
                while (start <= endval && p > k)
                {
                    p /= arr[start];
                    start++;
                }
            }
             
            if (p == k)
            {
                // Count number of succeeding ones.
                countOnes = 0;
                while (endval + 1 < n && arr[endval + 1] == 1)
                {
                    countOnes++;
                    endval++;
                }
                 
                // Update result by adding both new
                // subarray and effect of succeeding ones.
                res += (countOnes + 1);
                 
                // Update sliding window and result according
                // to change in sliding window. Here preceding
                // 1s have same effect on subarray as succeeding
                // 1s, so simply add.
                while (start <= endval && arr[start] == 1)
                {
                    res += (countOnes + 1);
                    start++;
                }
                 
                // Move start to correct position to find new
                // subarray and update product accordingly.
                p /= arr[start];
                start++;
            }
             
            endval++;
        }
        return res;
    }
     
    // Driver code
    public static void main (String[] args)
    {
        int arr[] = new int[]{ 2, 1, 1, 1, 4, 5 };
        int n = arr.length;
        int k = 4;
        System.out.println(findSubarrayCount(arr, n, k));
    }
}


Python3




# Python3 program to find number of subarrays
# having product exactly equal to k.
 
# Function to find number of subarrays
# having product equal to 1.
def countOne(arr, n) :
    i = 0
     
    # To store number of ones in
    # current segment of all 1s.
    Len = 0
     
    # To store number of subarrays
    # having product equal to 1.
    ans = 0
     
    while(i < n) :
         
        # If current element is 1, then
        # find length of segment of 1s
        # starting from current element.
        if(arr[i] == 1) :
            Len = 0
            while(i < n and arr[i] == 1) :
                i += 1
                Len += 1
             
            # add number of possible
            # subarrays of 1 to result.
            ans += (Len*(Len+1)) // 2
        i += 1
     
    return ans
 
# Function to find number of subarrays having
# product exactly equal to k.
def findSubarrayCount(arr, n, k) :
 
    start, endval, p, countOnes, res = 0, 0, 1, 0, 0
 
    while (endval < n) :
     
        p = p * (arr[endval])
 
        # If product is greater than k then we need to decrease
        # it. This could be done by shifting starting point of
        # sliding window one place to right at a time and update
        # product accordingly.
        if(p > k) :
         
            while(start <= endval and p > k) :
             
                p = p // arr[start]
                start += 1
                 
        if(p == k) :
         
            # Count number of succeeding ones.
            countOnes = 0
            while endval + 1 < n and arr[endval + 1] == 1 :
              
                countOnes += 1
                endval += 1
 
            # Update result by adding both new subarray
            # and effect of succeeding ones.
            res += (countOnes + 1)
 
            # Update sliding window and result according
            # to change in sliding window. Here preceding
            # 1s have same effect on subarray as succeeding
            # 1s, so simply add.
            while(start <= endval and arr[start] == 1 and k!=1) :
             
                res += (countOnes + 1)
                start += 1
 
            # Move start to correct position to find new
            # subarray and update product accordingly.
            p = p // arr[start]
            start += 1
 
        endval += 1
 
    return res
 
arr1 = [ 2, 1, 1, 1, 3, 1, 1, 4 ]
n1 = len(arr1)
k = 1
 
if(k != 1) :
    print(findSubarrayCount(arr1, n1, k))
else :
    print(countOne(arr1, n1))
 
arr2 = [ 2, 1, 1, 1, 4, 5]
n2 = len(arr2)
k = 4
 
if(k != 1) :
    print(findSubarrayCount(arr2, n2, k))
else :
    print(countOne(arr2, n2))
 
    # This code is contributed by divyesh072019


C#




// C# program to find number
// of subarrays having product
// exactly equal to k.
using System;
 
class GFG
{
    // Function to find number of
    // subarrays having product
    // exactly equal to k.
    public static int findSubarrayCount(int []arr,
                                        int n, int k)
    {
        int start = 0, endval = 0;
        int p = 1, countOnes = 0, res = 0;
        while(endval < n)
        {
            p *= (arr[endval]);
             
            // If product is greater than k
            // then we need to decrease it.
            // This could be done by shifting
            // starting point of sliding window
            // one place to right at a time and
            // update product accordingly.
            if (p > k)
            {
                while (start <= endval && p > k)
                {
                    p /= arr[start];
                    start++;
                }
            }
             
            if (p == k)
            {
                // Count number of
                // succeeding ones.
                countOnes = 0;
                while (endval + 1 < n &&
                       arr[endval + 1] == 1)
                {
                    countOnes++;
                    endval++;
                }
                 
                // Update result by adding
                // both new subarray and
                // effect of succeeding ones.
                res += (countOnes + 1);
                 
                // Update sliding window and
                // result according to change
                // in sliding window. Here
                // preceding 1s have same
                // effect on subarray as
                // succeeding 1s, so simply add.
                while (start <= endval &&
                       arr[start] == 1)
                {
                    res += (countOnes + 1);
                    start++;
                }
                 
                // Move start to correct position
                // to find new subarray and update
                // product accordingly.
                p /= arr[start];
                start++;
            }
             
            endval++;
        }
        return res;
    }
     
    // Driver code
    public static void Main ()
    {
        int []arr = new int[]{ 2, 1, 1,
                               1, 4, 5 };
        int n = arr.Length;
        int k = 4;
        Console.WriteLine(findSubarrayCount(arr, n, k));
    }
}
 
// This code is contributed by anuj_67.


PHP




<?php
// PHP program to find number of subarrays
// having product exactly equal to k.
 
// Function to find number of subarrays
// having product exactly equal to k.
function findSubarrayCount($arr, $n, $k)
{
    $start = 0;
    $endval = 0;
    $p = 1;
    $countOnes = 0;
    $res = 0;
 
    while ($endval < $n)
    {
        $p *= ($arr[$endval]);
 
        // If product is greater than k
        // then we need to decrease it.
        // This could be done by shifting
        // starting point of sliding window
        // one place to right at a time and
        // update product accordingly.
        if($p > $k)
        {
            while($start <= $endval && $p > $k)
            {
                $p /= $arr[$start];
                $start++;
            }
        }
         
         
        if($p == $k)
        {
             
            // Count number of
            // succeeding ones.
            $countOnes = 0;
            while($endval + 1 < $n &&
                 $arr[$endval + 1] == 1)
            {
                $countOnes++;
                $endval++;
            }
 
            // Update result by adding
            // both new subarray and
            // effect of succeeding ones.
            $res += ($countOnes + 1);
 
            // Update sliding window and
            // result according to change
            // in sliding window. Here
            // preceding 1s have same
            // effect on subarray as
            // succeeding 1s, so simply
            // add.
            while($start <= $endval &&
                  $arr[$start] == 1)
            {
                $res += ($countOnes + 1);
                $start++;
            }
 
            // Move start to correct
            // position to find new
            // subarray and update
            // product accordingly.
            $p /= $arr[$start];
            $start++;
        }
 
        $endval++;
    }
    return $res;
}
 
    // Driver Code
    $arr = array(2, 1, 1, 1, 4, 5);
    $n = sizeof($arr) ;
    $k = 4;
    echo findSubarrayCount($arr, $n, $k);
     
// This code is contributed by aj_36
?>


Javascript




<script>
 
// Javascript program to find number of subarrays
// having product exactly equal to k.
 
// Function to find number of subarrays
// having product equal to 1.
function countOne(arr, n)
{
    let i = 0;
 
    // To store number of ones in
    // current segment of all 1s.
    let len = 0;
 
    // To store number of subarrays
    // having product equal to 1.
    let ans = 0;
 
    while (i < n)
    {
         
        // If current element is 1, then
        // find length of segment of 1s
        // starting from current element.
        if (arr[i] == 1)
        {
            len = 0;
            while (i < n && arr[i] == 1)
            {
                i++;
                len++;
            }
 
            // Add number of possible
            // subarrays of 1 to result.
            ans += parseInt((len * (len + 1)) / 2, 10);
        }
        i++;
    }
    return ans;
}
 
/// Function to find number of subarrays having
/// product exactly equal to k.
function findSubarrayCount(arr, n, k)
{
    let start = 0, endval = 0, p = 1,
        countOnes = 0, res = 0;
 
    while (endval < n)
    {
        p *= (arr[endval]);
 
        // If product is greater than k then we
        // need to decrease it. This could be
        // done by shifting starting point of
        // sliding window one place to right
        // at a time and update product accordingly.
        if (p > k)
        {
            while (start <= endval && p > k)
            {
                p = parseInt(p / arr[start], 10);
                start++;
            }
        }
 
        if (p == k)
        {
             
            // Count number of succeeding ones.
            countOnes = 0;
            while (endval + 1 < n && arr[endval + 1] == 1)
            {
                countOnes++;
                endval++;
            }
 
            // Update result by adding both new subarray
            // and effect of succeeding ones.
            res += (countOnes + 1);
 
            // Update sliding window and result according
            // to change in sliding window. Here preceding
            // 1s have same effect on subarray as succeeding
            // 1s, so simply add.
            while(start <= endval &&
                  arr[start] == 1 && k != 1)
            {
                res += (countOnes + 1);
                start++;
            }
 
            // Move start to correct position to find new
            // subarray and update product accordingly.
            p = parseInt(p / arr[start], 10);
            start++;
        }
        endval++;
    }
    return res;
}
 
// Driver code
let arr1 = [ 2, 1, 1, 1, 3, 1, 1, 4 ];
let n1 = arr1.length;
let k = 1;
  
if (k != 1)
    document.write(findSubarrayCount(arr1, n1, k) + "</br>");
else
    document.write(countOne(arr1, n1) + "</br>");
  
let arr2 = [ 2, 1, 1, 1, 4, 5 ];
let n2 = arr2.length;
k = 4;
  
if (k != 1)
    document.write(findSubarrayCount(arr2, n2, k) + "</br>");
else
    document.write(countOne(arr2, n2) + "</br>");
         
// This code is contributed by suresh07
 
</script>


Output: 

9
4

 

Time Complexity: O(n) 
Auxiliary Space : O(1)



Last Updated : 05 Aug, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads