📌  相关文章
📜  具有给定产品的子数组的数量

📅  最后修改于: 2022-05-13 01:57:50.209000             🧑  作者: Mango

具有给定产品的子数组的数量

给定一个正数数组和一个数 k,找出乘积正好等于 k 的子数组的数量。我们可以假设没有溢出。

例子 :

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]

一个简单的解决方案是考虑所有子数组并找到它们的乘积。对于每个产品,检查它是否等于 k。如果是,则增加结果。

一个有效的解决方案是使用滑动窗口技术来解决问题。我们用两个指针 start 和 end 来表示滑动窗口的起点和终点。
最初 start 和 end 都指向数组的开头,即索引 0。继续递增 end 直到 product p < k。一旦 p 等于 k 停止递增 end 并检查 end 的当前位置是否跟在数组中的一系列 1 之后。如果是,那么那些 1 也将有助于子数组计数。将这些后续 1 的计数存储在变量 countOnes 中。在此之后继续递增 start 直到 p 等于 k,同时将 (countOnes + 1) 添加到结果。如果 start 与 end 重合,则再次从递增 end 开始并遵循相同的过程。这样做直到 end < 数组大小。

为什么 countOnes + 1 被添加到结果中?
考虑上述示例案例中的第二个测试案例。如果我们按照上面提到的过程,那么在增加 end 之后,我们将到达 start = 0 和 end = 3。在此之后 countOnes 被设置为等于 1。 start = 0 有多少子数组?有两个子数组:arr[0..3] 和 arr[0..4]。观察 subarray[0..3] 是我们使用滑动窗口技术发现的。这会将结果计数增加 1,并且在表达式 countOnes + 1 中由 + 1 表示。另一个子数组 [0..4] 只需通过将单个 1 附加到子数组 [0..3] 来获得,即添加 countOnes 数1s 一次。让我们试着概括一下。假设 arr[0..i] 是使用滑动窗口技术获得的子数组,并且让 countOnes = j。然后我们可以通过将单个 1 附加到该子数组来一次将该子数组扩展单位长度。将单个 1 附加到 arr[0..i] 后,新的子数组是 arr[0..i+1] 并且结果也增加了 1。countOnes 现在减少 1 并等于 j – 1。我们可以连续追加单个一次 1 并获得一个新的子数组,直到 countOnes 不等于 0。
因此,结果计数增加了 countOnes,并在表达式 countOnes + 1 中表示为 countOnes。因此,对于 start 中的每个增量,直到 p 等于 k,只需将 countOnes + 1 添加到结果中。

请注意,上述算法不适用于 k = 1 的情况。例如,考虑测试用例 arr[] = {2, 1, 1, 1}。感谢Jeel Santoki提供这个测试用例。对于 k = 1 的情况,我们将找到所有元素为 1 的数组的每个段的长度。设 1 的特定段的长度为 x。该段的子数组数将为 x*(x+1)/2。所有这些子数组都将具有乘积 1,因为所有元素都是 1。在给定的测试用例中,从索引 1 到索引 3 只有一个段为 1,长度为 3。因此,乘积为 1 的子数组的总数为 (3*4)/2 = 6 .

该算法可以列举为:

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.

执行:

C++
// C++ program to find number of subarrays
// having product exactly equal to k.
#include 
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
 $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


输出:
9
4

时间复杂度: O(n)
辅助空间: O(1)