C++程序 查找第 k 大的子数组之和

C++程序 查找第 k 大的子数组之和

给定一个整数数组。编写一个程序,在其中寻找具有负数和正数的数字的连续子数组的第k大的和。

例子:

Input: a[] = {20, -5, -1} 
         k = 3
Output: 14
Explanation: 所有连续子数组的和为(20, 15, 14, -5, -6, -1),因此第3大的和为14。

Input: a[] = {10, -10, 20, -40} 
         k = 6
Output: -10 
Explanation: 所有连续子数组的和的第6大值是-10。

一种 暴力破解的方法 是将所有连续和存储在另一个数组中,然后对其进行排序并打印第k大的值。但是,当元素的数量很大时,在存储连续和的数组中,由于连续子数组的数量将会很大(二次方),所以该方法将会消耗大量的内存。

一种 高效的方法 是在sum[]数组中存储该数组的预和。我们可以根据索引i和j来寻找从i到j的连续子数组的和,公式如下:sum[j] – sum[i-1]。

为了存储第k大的和,可以使用小根堆(优先队列),其中我们将连续和压入小根堆中,直到我们得到K个元素,一旦我们有了K个元素,就检查该元素是否大于插入到小根堆中的第K个元素,如果是,则将其插入到小根堆中并弹出小根堆中的顶部元素,否则不插入。 最后,小根堆中的顶部元素将是您的答案。

下面是上述方法的实现。

// CPP program to find the k-th largest sum
// of subarray
#include <bits/stdc++.h>
using namespace std;
  
// function to calculate kth largest element
// in contiguous subarray sum
int kthLargestSum(int arr[], int n, int k)
{
    // array to store predix sums
    int sum[n + 1];
    sum[0] = 0;
    sum[1] = arr[0];
    for (int i = 2; i <= n; i++)
        sum[i] = sum[i - 1] + arr[i - 1];
  
    // priority_queue of min heap
    priority_queue<int, vector<int>, greater<int> > Q;
  
    // loop to calculate the contiguous subarray
    // sum position-wise
    for (int i = 1; i <= n; i++)
    {
  
        // loop to traverse all positions that
        // form contiguous subarray
        for (int j = i; j <= n; j++)
        {
            // calculates the contiguous subarray
            // sum from j to i index
            int x = sum[j] - sum[i - 1];
  
            // if queue has less then k elements,
            // then simply push it
            if (Q.size() < k)
                Q.push(x);
  
            else
            {
                // it the min heap has equal to
                // k elements then just check
                // if the largest kth element is
                // smaller than x then insert
// else its of no use
                if (Q.top() < x)
                {
                    Q.pop();
                    Q.push(x);
                }
            }
        }
    }
  
    // the top element will be then kth
    // largest element
    return Q.top();
}
  
// Driver program to test above function
int main()
{
    int a[] = { 10, -10, 20, -40 };
    int n = sizeof(a) / sizeof(a[0]);
    int k = 6;
  
    // calls the function to find out the
    // k-th largest sum
    cout << kthLargestSum(a, n, k);
    return 0;
}  

输出:

-10

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

辅助空间: 小根堆使用了O(k)的额外空间,而我们可以将和数组存储在数组本身中,因为它是没有用的。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

C++ 示例