📜  乘积小于K的子阵列数

📅  最后修改于: 2021-05-06 22:06:05             🧑  作者: Mango

给定一个正数数组,计算乘积小于给定数K的可能连续子数组的数量。

例子 :

Input : arr[] = [1, 2, 3, 4] 
        K = 10
Output : 7
The subarrays are {1}, {2}, {3}, {4}
{1, 2}, {1, 2, 3} and {2, 3}

Input  : arr[] = [1, 9, 2, 8, 6, 4, 3] 
         K = 100
Output : 16

Input  : arr[] = [10, 5, 2, 6] 
         K = 100
Output : 8

解决此问题的一种简单方法是生成数组的所有子数组,然后计算乘积大于K的数组的数量。
下面是上述方法的实现:

C++
// CPP program to count subarrays having
// product less than k.
#include 
using namespace std;
 
int countsubarray(int array[], int n, int k)
{
    int count = 0;
    int i, j, mul;
 
    for (i = 0; i < n; i++) {
        // Counter for single element
        if (array[i] < k)
            count++;
 
        mul = array[i];
 
        for (j = i + 1; j < n; j++) {
            // Multiple subarray
            mul = mul * array[j];
            // If this multiple is less
            // than k, then increment
            if (mul < k)
                count++;
            else
                break;
        }
    }
 
    return count;
}
 
// Driver Code
int main()
{
    int array[] = { 1, 2, 3, 4 };
    int k = 10;
    int size = sizeof(array) / sizeof(array[0]);
    int count = countsubarray(array, size, k);
    cout << count << "\n";
}
 
// This code is contributed by  'Dev Agarwal'.


Java
// Java program to count subarrays
// having product less than k.
class GFG {
    static int countsubarray(int array[], int n, int k)
    {
        int count = 0;
        int i, j, mul;
 
        for (i = 0; i < n; i++) {
 
            // Counter for single element
            if (array[i] < k)
                count++;
 
            mul = array[i];
 
            for (j = i + 1; j < n; j++) {
 
                // Multiple subarray
                mul = mul * array[j];
 
                // If this multiple is less
                // than k, then increment
                if (mul < k)
                    count++;
                else
                    break;
            }
        }
 
        return count;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int array[] = { 1, 2, 3, 4 };
        int k = 10;
        int size = array.length;
 
        int count = countsubarray(array, size, k);
        System.out.print(count);
    }
}
 
// This code is contributed by Sam007


Python3
# Python3 program to count subarrays
# having product less than k.
 
 
def countsubarray(array, n, k):
    count = 0
    for i in range(0, n):
 
        # Counter for single element
        if array[i] < k:
            count += 1
 
        mul = array[i]
 
        for j in range(i + 1, n):
 
            # Multiple subarray
            mul = mul * array[j]
 
            # If this multiple is less
            # than k, then increment
            if mul < k:
                count += 1
            else:
                break
    return count
 
 
# Driver Code
array = [1, 2, 3, 4]
k = 10
size = len(array)
count = countsubarray(array, size, k)
print(count, end=" ")
 
# This code is contributed by Shreyanshi Arun.


C#
// C# program to count subarrays having
// product less than k.
using System;
 
public class GFG {
 
    static int countsubarray(int[] array, int n, int k)
    {
        int count = 0;
        int i, j, mul;
 
        for (i = 0; i < n; i++) {
 
            // Counter for single element
            if (array[i] < k)
                count++;
 
            mul = array[i];
 
            for (j = i + 1; j < n; j++) {
 
                // Multiple subarray
                mul = mul * array[j];
 
                // If this multiple is less
                // than k, then increment
                if (mul < k)
                    count++;
                else
                    break;
            }
        }
 
        return count;
    }
 
    // Driver Code
    static public void Main()
    {
        int[] array = { 1, 2, 3, 4 };
        int k = 10;
        int size = array.Length;
 
        int count = countsubarray(array, size, k);
 
        Console.WriteLine(count);
    }
}
 
// This code is contributed by vt_m.


PHP


Javascript


C++
// CPP program to count subarrays having product
// less than k.
#include 
#include 
using namespace std;
 
int countSubArrayProductLessThanK(const vector& a,
                                  long long k)
{
    const int n = a.size();
    long long p = 1;
    int res = 0;
    for (int start = 0, end = 0; end < n; end++) {
 
        // Move right bound by 1 step. Update the product.
        p *= a[end];
 
        // Move left bound so guarantee that p is again
        // less than k.
        while (start < end && p >= k)
            p /= a[start++];
 
        // If p is less than k, update the counter.
        // Note that this is working even for (start ==
        // end): it means that the previous window cannot
        // grow anymore and a single array element is the
        // only addendum.
        if (p < k) {
            int len = end - start + 1;
            res += len;
        }
    }
 
    return res;
}
 
// Driver Code
int main()
{
    // Function Calls
    cout << countSubArrayProductLessThanK({ 1, 2, 3, 4 },
                                          10)
         << endl;
    cout << countSubArrayProductLessThanK(
                { 1, 9, 2, 8, 6, 4, 3 }, 100)
         << endl;
    cout << countSubArrayProductLessThanK({ 5, 3, 2 }, 16)
         << endl;
    cout << countSubArrayProductLessThanK({ 100, 200 }, 100)
         << endl;
    cout << countSubArrayProductLessThanK({ 100, 200 }, 101)
         << endl;
}


Java
// Java program to count subarrays having
// product less than k.
import java.util.*;
 
class GFG {
 
    static int
    countSubArrayProductLessThanK(ArrayList a,
                                  long k)
    {
        int n = a.size();
        long p = 1;
        int res = 0;
        for (int start = 0, end = 0; end < n; end++) {
 
            // Move right bound by 1 step.
            // Update the product.
            p *= a.get(end);
 
            // Move left bound so guarantee that
            // p is again less than k.
            while (start < end && p >= k)
                p /= a.get(start++);
 
            // If p is less than k, update the counter.
            // Note that this is working even for
            // (start == end): it means that the
            // previous window cannot grow anymore
            // and a single array element is the only
            // addendum.
            if (p < k) {
                int len = end - start + 1;
                res += len;
            }
        }
 
        return res;
    }
 
    // Drive Code
    public static void main(String[] args)
    {
       // Function Calls
        ArrayList al = new ArrayList();
        al.add(1);
        al.add(2);
        al.add(3);
        al.add(4);
        System.out.println(
            countSubArrayProductLessThanK(al, 10));
 
        ArrayList al1 = new ArrayList();
        al1.add(1);
        al1.add(9);
        al1.add(2);
        al1.add(8);
        al1.add(6);
        al1.add(4);
        al1.add(3);
        System.out.println(
            countSubArrayProductLessThanK(al1, 100));
 
        ArrayList al2 = new ArrayList();
        al2.add(5);
        al2.add(3);
        al2.add(2);
        System.out.println(
            countSubArrayProductLessThanK(al2, 16));
 
        ArrayList al3 = new ArrayList();
        al3.add(100);
        al3.add(200);
        System.out.println(
            countSubArrayProductLessThanK(al3, 100));
 
        ArrayList al4 = new ArrayList();
        al4.add(100);
        al4.add(200);
        System.out.println(
            countSubArrayProductLessThanK(al3, 101));
    }
}
// This code is contributed by Prerna Saini


Python3
# Python3 program to count
# subarrays having product
# less than k.
 
 
def countSubArrayProductLessThanK(a, k):
    n = len(a)
    p = 1
    res = 0
    start = 0
    end = 0
    while(end < n):
 
        # Move right bound by 1
        # step. Update the product.
        p *= a[end]
 
        # Move left bound so guarantee
        # that p is again less than k.
        while (start < end and p >= k):
            p = int(p//a[start])
            start += 1
 
        # If p is less than k, update
        # the counter. Note that this
        # is working even for (start == end):
        # it means that the previous
        # window cannot grow anymore
        # and a single array element
        # is the only addendum.
        if (p < k):
            l = end - start + 1
            res += l
 
        end += 1
 
    return res
 
 
# Driver Code
if __name__ == '__main__':
    print(countSubArrayProductLessThanK([1, 2, 3, 4], 10))
    print(countSubArrayProductLessThanK([1, 9, 2, 8, 6, 4, 3], 100))
    print(countSubArrayProductLessThanK([5, 3, 2], 16))
    print(countSubArrayProductLessThanK([100, 200], 100))
    print(countSubArrayProductLessThanK([100, 200], 101))
 
# This code is contributed by mits


C#
// C# program to count subarrays
// having product less than k.
using System;
using System.Collections;
 
class GFG {
    static int countSubArrayProductLessThanK(ArrayList a,
                                             int k)
    {
        int n = a.Count;
        int p = 1;
        int res = 0;
        for (int start = 0, end = 0; end < n; end++) {
 
            // Move right bound by 1 step.
            // Update the product.
            p *= (int)a[end];
 
            // Move left bound so guarantee
            // that p is again less than k.
            while (start < end && p >= k)
                p /= (int)a[start++];
 
            // If p is less than k, update the
            // counter. Note that this is working
            // even for (start == end): it means
            // that the previous window cannot
            // grow anymore and a single array
            // element is the only Addendum.
            if (p < k) {
                int len = end - start + 1;
                res += len;
            }
        }
 
        return res;
    }
 
    // Driver Code
    static void Main()
    {
        ArrayList al = new ArrayList();
        al.Add(1);
        al.Add(2);
        al.Add(3);
        al.Add(4);
        Console.WriteLine(
            countSubArrayProductLessThanK(al, 10));
 
        ArrayList al1 = new ArrayList();
        al1.Add(1);
        al1.Add(9);
        al1.Add(2);
        al1.Add(8);
        al1.Add(6);
        al1.Add(4);
        al1.Add(3);
        Console.WriteLine(
            countSubArrayProductLessThanK(al1, 100));
 
        ArrayList al2 = new ArrayList();
        al2.Add(5);
        al2.Add(3);
        al2.Add(2);
        Console.WriteLine(
            countSubArrayProductLessThanK(al2, 16));
 
        ArrayList al3 = new ArrayList();
        al3.Add(100);
        al3.Add(200);
        Console.WriteLine(
            countSubArrayProductLessThanK(al3, 100));
 
        ArrayList al4 = new ArrayList();
        al4.Add(100);
        al4.Add(200);
        Console.WriteLine(
            countSubArrayProductLessThanK(al3, 101));
    }
}
 
// This code is contributed by mits


PHP
= $k)
            $p /= $a[$start++];
         
        // If p is less than k, update
        // the counter. Note that this
        // is working even for (start == end):
        // it means that the previous
        // window cannot grow anymore
        // and a single array element
        // is the only addendum.
        if ($p < $k)
        {
            $len = $end - $start + 1;
            $res += $len;
        }
    }
 
    return $res;
}
 
// Driver Code
echo countSubArrayProductLessThanK(
             array(1, 2, 3, 4), 10) . "\n";
echo countSubArrayProductLessThanK(
             array(1, 9, 2, 8, 6, 4, 3), 100) . "\n";
echo countSubArrayProductLessThanK(
             array(5, 3, 2), 16) . "\n";
echo countSubArrayProductLessThanK(
             array(100, 200), 100) . "\n";
echo countSubArrayProductLessThanK(
             array(100, 200), 101) . "\n";
     
// This code is contributed by mits
?>


输出
7

时间复杂度: O(n ^ 2)。

我们可以基于滑动窗口技术来优化方法(注意,我们需要找到连续的部分)
首先,根据描述,数组中的所有元素都严格为正。还要假设所有数组元素的乘积始终适合64位整数类型。考虑到这两点,我们能够对数组元素的安全性进行乘除(无零除法,无溢出)。

让我们看看如何计算所需的金额。假设我们在开始和结束之间有一个窗口,并且所有元素的乘积为p

情况1. p * x
这意味着我们可以将窗口的右边界再移一步。此步骤会产生多少个连续数组?它是:1 +(结束开始)。
实际上,元素本身包含一个数组,我们也可以将x添加到所有具有右边界的连续数组中。这样的数组与窗口的长度一样多。

情况2. p * x> = k
这意味着我们必须首先调整窗口的左边框,以使乘积再次小于k。之后,我们可以应用案例1中的公式。

例子 :

a = [5, 3, 2]
  k = 16
 
  counter = 0
  Window: [5]
  Product: 5

  5  counter += 1+ (0-0)
  counter = 1
  Window: [5,3]
  Product: 15

  15  counter += 1 + (1-0)
  counter = 3
  Window: [5,3,2]
  Product: 30

  30 > 16 --> Adjust the left border
  New Window: [3,2]
  New Product: 6

  6  counter += 1 + (2-1)
  counter = 5
  Answer: 5 

C++

// CPP program to count subarrays having product
// less than k.
#include 
#include 
using namespace std;
 
int countSubArrayProductLessThanK(const vector& a,
                                  long long k)
{
    const int n = a.size();
    long long p = 1;
    int res = 0;
    for (int start = 0, end = 0; end < n; end++) {
 
        // Move right bound by 1 step. Update the product.
        p *= a[end];
 
        // Move left bound so guarantee that p is again
        // less than k.
        while (start < end && p >= k)
            p /= a[start++];
 
        // If p is less than k, update the counter.
        // Note that this is working even for (start ==
        // end): it means that the previous window cannot
        // grow anymore and a single array element is the
        // only addendum.
        if (p < k) {
            int len = end - start + 1;
            res += len;
        }
    }
 
    return res;
}
 
// Driver Code
int main()
{
    // Function Calls
    cout << countSubArrayProductLessThanK({ 1, 2, 3, 4 },
                                          10)
         << endl;
    cout << countSubArrayProductLessThanK(
                { 1, 9, 2, 8, 6, 4, 3 }, 100)
         << endl;
    cout << countSubArrayProductLessThanK({ 5, 3, 2 }, 16)
         << endl;
    cout << countSubArrayProductLessThanK({ 100, 200 }, 100)
         << endl;
    cout << countSubArrayProductLessThanK({ 100, 200 }, 101)
         << endl;
}

Java

// Java program to count subarrays having
// product less than k.
import java.util.*;
 
class GFG {
 
    static int
    countSubArrayProductLessThanK(ArrayList a,
                                  long k)
    {
        int n = a.size();
        long p = 1;
        int res = 0;
        for (int start = 0, end = 0; end < n; end++) {
 
            // Move right bound by 1 step.
            // Update the product.
            p *= a.get(end);
 
            // Move left bound so guarantee that
            // p is again less than k.
            while (start < end && p >= k)
                p /= a.get(start++);
 
            // If p is less than k, update the counter.
            // Note that this is working even for
            // (start == end): it means that the
            // previous window cannot grow anymore
            // and a single array element is the only
            // addendum.
            if (p < k) {
                int len = end - start + 1;
                res += len;
            }
        }
 
        return res;
    }
 
    // Drive Code
    public static void main(String[] args)
    {
       // Function Calls
        ArrayList al = new ArrayList();
        al.add(1);
        al.add(2);
        al.add(3);
        al.add(4);
        System.out.println(
            countSubArrayProductLessThanK(al, 10));
 
        ArrayList al1 = new ArrayList();
        al1.add(1);
        al1.add(9);
        al1.add(2);
        al1.add(8);
        al1.add(6);
        al1.add(4);
        al1.add(3);
        System.out.println(
            countSubArrayProductLessThanK(al1, 100));
 
        ArrayList al2 = new ArrayList();
        al2.add(5);
        al2.add(3);
        al2.add(2);
        System.out.println(
            countSubArrayProductLessThanK(al2, 16));
 
        ArrayList al3 = new ArrayList();
        al3.add(100);
        al3.add(200);
        System.out.println(
            countSubArrayProductLessThanK(al3, 100));
 
        ArrayList al4 = new ArrayList();
        al4.add(100);
        al4.add(200);
        System.out.println(
            countSubArrayProductLessThanK(al3, 101));
    }
}
// This code is contributed by Prerna Saini

Python3

# Python3 program to count
# subarrays having product
# less than k.
 
 
def countSubArrayProductLessThanK(a, k):
    n = len(a)
    p = 1
    res = 0
    start = 0
    end = 0
    while(end < n):
 
        # Move right bound by 1
        # step. Update the product.
        p *= a[end]
 
        # Move left bound so guarantee
        # that p is again less than k.
        while (start < end and p >= k):
            p = int(p//a[start])
            start += 1
 
        # If p is less than k, update
        # the counter. Note that this
        # is working even for (start == end):
        # it means that the previous
        # window cannot grow anymore
        # and a single array element
        # is the only addendum.
        if (p < k):
            l = end - start + 1
            res += l
 
        end += 1
 
    return res
 
 
# Driver Code
if __name__ == '__main__':
    print(countSubArrayProductLessThanK([1, 2, 3, 4], 10))
    print(countSubArrayProductLessThanK([1, 9, 2, 8, 6, 4, 3], 100))
    print(countSubArrayProductLessThanK([5, 3, 2], 16))
    print(countSubArrayProductLessThanK([100, 200], 100))
    print(countSubArrayProductLessThanK([100, 200], 101))
 
# This code is contributed by mits

C#

// C# program to count subarrays
// having product less than k.
using System;
using System.Collections;
 
class GFG {
    static int countSubArrayProductLessThanK(ArrayList a,
                                             int k)
    {
        int n = a.Count;
        int p = 1;
        int res = 0;
        for (int start = 0, end = 0; end < n; end++) {
 
            // Move right bound by 1 step.
            // Update the product.
            p *= (int)a[end];
 
            // Move left bound so guarantee
            // that p is again less than k.
            while (start < end && p >= k)
                p /= (int)a[start++];
 
            // If p is less than k, update the
            // counter. Note that this is working
            // even for (start == end): it means
            // that the previous window cannot
            // grow anymore and a single array
            // element is the only Addendum.
            if (p < k) {
                int len = end - start + 1;
                res += len;
            }
        }
 
        return res;
    }
 
    // Driver Code
    static void Main()
    {
        ArrayList al = new ArrayList();
        al.Add(1);
        al.Add(2);
        al.Add(3);
        al.Add(4);
        Console.WriteLine(
            countSubArrayProductLessThanK(al, 10));
 
        ArrayList al1 = new ArrayList();
        al1.Add(1);
        al1.Add(9);
        al1.Add(2);
        al1.Add(8);
        al1.Add(6);
        al1.Add(4);
        al1.Add(3);
        Console.WriteLine(
            countSubArrayProductLessThanK(al1, 100));
 
        ArrayList al2 = new ArrayList();
        al2.Add(5);
        al2.Add(3);
        al2.Add(2);
        Console.WriteLine(
            countSubArrayProductLessThanK(al2, 16));
 
        ArrayList al3 = new ArrayList();
        al3.Add(100);
        al3.Add(200);
        Console.WriteLine(
            countSubArrayProductLessThanK(al3, 100));
 
        ArrayList al4 = new ArrayList();
        al4.Add(100);
        al4.Add(200);
        Console.WriteLine(
            countSubArrayProductLessThanK(al3, 101));
    }
}
 
// This code is contributed by mits

的PHP

= $k)
            $p /= $a[$start++];
         
        // If p is less than k, update
        // the counter. Note that this
        // is working even for (start == end):
        // it means that the previous
        // window cannot grow anymore
        // and a single array element
        // is the only addendum.
        if ($p < $k)
        {
            $len = $end - $start + 1;
            $res += $len;
        }
    }
 
    return $res;
}
 
// Driver Code
echo countSubArrayProductLessThanK(
             array(1, 2, 3, 4), 10) . "\n";
echo countSubArrayProductLessThanK(
             array(1, 9, 2, 8, 6, 4, 3), 100) . "\n";
echo countSubArrayProductLessThanK(
             array(5, 3, 2), 16) . "\n";
echo countSubArrayProductLessThanK(
             array(100, 200), 100) . "\n";
echo countSubArrayProductLessThanK(
             array(100, 200), 101) . "\n";
     
// This code is contributed by mits
?>

输出 :

7
16
5
0
1

复杂度:数组中的每个元素最多可访问两次,因此,这是O(n)时间复杂度。使用了几个标量变量,因此,它是O(1)多余的空间。

练习1:更新解决方案,以便它可以处理输入数组中的nil。
练习2:更新解决方案,以便在计算乘积时可以处理乘法溢出。