给定一个由N 个整数和两个整数M和K 组成的数组 arr[] 。任务是检查连续子数组的 K 个最大和的乘积是否大于M 。
例子:
Input: arr[] = {10, -4, -2, 7}, M = 659, K = 3
Output: Yes
The 3 largest contiguous sums for the subarrays
are of the subarrays {10, -4, -2, 7}, {10} and {7}
i.e. 11, 10 and 7, the product is 11 * 10 * 7 = 770
which is greater than 659.
Input: arr[] = {4, -3, 8}, M = 100, K = 6
Output: No
一种蛮力方法是将连续子数组的所有和存储在其他数组中并对其进行排序,然后计算 K 最大和的乘积并检查该值是否大于 M。但如果数组的大小为太大,连续子阵列的数量会增加,因此辅助阵列将占用更多空间。
更好的方法是将数组的前缀和存储在数组本身中。然后子数组arr[i…j]的总和可以计算为arr[j] – arr[i – 1] 。现在为了存储K 个最大和的连续子数组,使用一个最小堆(优先级队列),其中一次只存储 K 个最大和。之后,对于每个其他元素,检查该元素是否大于最小堆的顶部元素,如果是,则该元素将被插入到最小堆中,并且顶部元素将从最小堆中弹出。最后,计算最小堆中所有元素的乘积并检查它是否大于M。
下面是上述方法的实现:
// C++ implementation of the approach
#include
using namespace std;
// Function that returns true is the product
// of the maximum K subarrays sums of
// arr[] is greater than M
bool checkKSum(int arr[], int n, int k, int M)
{
// Update the array to store the prefix sum
for (int i = 1; i < n; i++)
arr[i] = arr[i - 1] + arr[i];
// Min-heap
priority_queue, greater > Q;
// Starting index of the subarray
for (int i = 0; i < n; i++) {
// Ending index of the subarray
for (int j = i; j < n; j++) {
// To store the sum of the
// subarray arr[i...j]
int sum = (i == 0) ? arr[j] : arr[j] - arr[i - 1];
// If the queue has less then k elements
// then simply push it
if (Q.size() < k)
Q.push(sum);
else {
// If the min heap has equal exactly k
// elements then check if the current
// sum is greater than the smallest
// of the current k sums stored
if (Q.top() < sum) {
Q.pop();
Q.push(sum);
}
}
}
}
// Calculate the product of
// the k largest sum
long product = 1;
while (!Q.empty()) {
product *= Q.top();
Q.pop();
}
// If the product is greater than M
if (product > M)
return true;
return false;
}
// Driver code
int main()
{
int a[] = { 10, -4, -2, 7 };
int n = sizeof(a) / sizeof(a[0]);
int k = 3, M = 659;
if (checkKSum(a, n, k, M))
cout << "Yes";
else
cout << "No";
return 0;
}
Yes
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。