📌  相关文章
📜  计算平均值超过给定数组中位数的 K 长度子数组

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

计算平均值超过给定数组中位数的 K 长度子数组

给定一个由N个整数和一个正整数K组成的数组arr[] ,任务是找到大小为K的子数组的数量,其平均值大于其中位数且均值均大于其平均值,中位数必须是素数或非素数。

例子:

方法:给定的问题可以使用基于策略的数据结构(即ordered_set)来解决。请按照以下步骤解决给定的问题:

  • 使用 Sieve Of Eratosthenes 预先计算所有素数和非素数直到10 5
  • 初始化一个变量,比如存储子数组的结果计数的计数。
  • 找出 K个元素的平均值中位数,如果平均值 >= 中位数并且平均值和中位数都是素数或非素数,则将计数增加1
  • 将前K个数组元素存储在ordered_set中。
  • [0, N – K]范围内遍历给定数组并执行以下步骤:
    • 删除当前 来自ordered_set 的元素arr[i]并将第(i + k)元素,即arr[i + K]添加到ordered_set。
    • 使用函数find_order_by_set((K + 1)/2 – 1)找到数组的中值。
    • 求当前子数组的平均值。
    • 如果平均值 >= 中位数并且平均值和中位数都是素数或非素数,则将计数增加1
  • 完成上述步骤后,打印count的值作为结果。

下面是上述方法的实现。

C++
// C++ program for the above approach
 
#include 
#include 
#include 
#include 
using namespace __gnu_pbds;
 
using namespace std;
typedef tree,
             rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_set;
 
const int mxN = (int)1e5;
 
// Stores whether i is prime or not
bool prime[mxN + 1];
 
// Function to precompute all the prime
// numbers using sieve of eratosthenes
void SieveOfEratosthenes()
{
    // Initialize the prime array
    memset(prime, true, sizeof(prime));
 
    // Iterate over the range [2, mxN]
    for (int p = 2; p * p <= mxN; p++) {
 
        // If the prime[p] is unchanged,
        // then it is a prime
        if (prime[p]) {
 
            // Mark all multiples of p
            // as non-prime
            for (int i = p * p;
                 i <= mxN; i += p)
                prime[i] = false;
        }
    }
}
 
// Function to find number of subarrays
// that satisfy the given criteria
int countSubarray(int arr[], int n, int k)
{
    // Initialize the ordered_set
    ordered_set s;
 
    // Stores the sum for subarray
    int sum = 0;
    for (int i = 0; i < (int)k; i++) {
        s.insert(arr[i]);
        sum += arr[i];
    }
 
    // Stores the average for each
    // possible subarray
    int avgsum = sum / k;
 
    // Stores the count of subarrays
    int ans = 0;
 
    // For finding the median use the
    // find_by_order(k) that returns
    // an iterator to kth element
    int med = *s.find_by_order(
        (k + 1) / 2 - 1);
 
    // Check for the valid condition
    if (avgsum - med >= 0
        && ((prime[med] == 0
             && prime[avgsum] == 0)
            || (prime[med] != 0
                && prime[avgsum] != 0))) {
 
        // Increment the resultant
        // count of subarray
        ans++;
    }
 
    // Iterate the subarray over the
    // the range [0, N - K]
    for (int i = 0; i < (int)(n - k); i++) {
 
        // Erase the current element
        // arr[i]
        s.erase(s.find_by_order(
            s.order_of_key(arr[i])));
 
        // The function Order_of_key(k)
        // returns the number of items
        // that are strictly smaller
        // than K
        s.insert(arr[i + k]);
        sum -= arr[i];
 
        // Add the (i + k)th element
        sum += arr[i + k];
 
        // Find the average
        avgsum = sum / k;
 
        // Get the median value
        med = *s.find_by_order(
            (k + 1) / 2 - 1);
 
        // Check the condition
        if (avgsum - med >= 0
            && ((prime[med] == 0
                 && prime[avgsum] == 0)
                || (prime[med] != 0
                    && prime[avgsum] != 0))) {
 
            // Increment the count of
            // subarray
            ans++;
        }
    }
 
    // Return the resultant count
    // of subarrays
    return ans;
}
 
// Driver Code
int main()
{
    // Precompute all the primes
    SieveOfEratosthenes();
 
    int arr[] = { 2, 4, 3, 5, 6 };
    int K = 3;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << countSubarray(arr, N, K);
 
    return 0;
}


输出:
2

时间复杂度: O(N*log N + N*log(log N))
辅助空间: O(N)