📌  相关文章
📜  求所有奇数长度子数组的中位数之和

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

求所有奇数长度子数组的中位数之和

给定一个大小为N的数组arr[] ,任务是找到所有奇数长度子数组的中位数之和。

例子

先决条件:使用 STL 的运行整数流的中位数

天真的方法:生成每个子数组。如果子数组的长度为奇数,则对子数组进行排序并返回中间元素。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find sum of medians
// of all odd-length subarrays
int solve(vector arr)
{
    int ans = 0;
    int n = arr.size();
 
    // Loop to calculate the sum
    for(int i = 0; i < n; i++)
    {
        vector new_arr;
        for(int j = i; j < n; j++)
        {
            new_arr.push_back(arr[j]);
             
            // Odd length subarray
            if ((new_arr.size() % 2) == 1)
            {
                sort(new_arr.begin(), new_arr.end());
                int mid = new_arr.size() / 2;
                ans += new_arr[mid];
            }
        }
    }
    return ans;
}
 
// Driver Code
int main()
{
    vector arr = { 4, 2, 5, 1 };
    cout << solve(arr);
}
 
// This code is contributed by Samim Hossain Mondal.


Java
// Java program for the above approach
import java.util.*;
 
class GFG {
    // Function to find sum of medians
    // of all odd-length subarrays
    static int solve(int[] arr) {
        int ans = 0;
        int n = arr.length;
 
        // Loop to calculate the sum
        for (int i = 0; i < n; i++) {
            List new_arr = new LinkedList();
            for (int j = i; j < n; j++) {
                new_arr.add(arr[j]);
 
                // Odd length subarray
                if ((new_arr.size() % 2) == 1) {
                    Collections.sort(new_arr);
                    int mid = new_arr.size() / 2;
                    ans += new_arr.get(mid);
                }
            }
        }
        return ans;
    }
 
    // Driver Code
    public static void main(String[] args) {
        int[] arr = { 4, 2, 5, 1 };
        System.out.println(solve(arr));
    }
}
// This code is contributed by 29AjayKumar


Python3
# Python program for the above approach
 
# Function to find sum of medians
# of all odd-length subarrays
def solve(arr):
        ans = 0
        n = len(arr)
         
        # Loop to calculate the sum
        for i in range(n):
            new_arr = []
            for j in range(i, n, 1):
                new_arr.append(arr[j])
 
                # Odd length subarray
                if (len(new_arr)) % 2 == 1:
                    new_arr.sort()
                    mid = len(new_arr)//2
                    ans += new_arr[mid]
        return (ans)
 
# Driver Code
if __name__ == "__main__":
    arr = [4, 2, 5, 1]
    print(solve(arr))


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG
{
 
  // Function to find sum of medians
  // of all odd-length subarrays
  static int solve(int[] arr) {
    int ans = 0;
    int n = arr.Length;
 
    // Loop to calculate the sum
    for (int i = 0; i < n; i++) {
      List new_arr = new List();
      for (int j = i; j < n; j++) {
        new_arr.Add(arr[j]);
 
        // Odd length subarray
        if ((new_arr.Count % 2) == 1) {
          new_arr.Sort();
          int mid = new_arr.Count / 2;
          ans += new_arr[mid];
        }
      }
    }
    return ans;
  }
 
  // Driver Code
  public static void Main() {
    int[] arr = { 4, 2, 5, 1 };
    Console.Write(solve(arr));
  }
}
 
// This code is contributed by Saurabh Jaiswal


Javascript


Python3
# Python program for the above approach
from heapq import heappush as push, heappop as pop
 
# Find the sum of medians of odd-length
# subarrays
 
 
class find_median():
 
    # Constructor to declare two heaps
    def __init__(self):
 
        # Store lower half elements such that
        # maximum element is at top
        self.max_heap = []
 
        # Store higher half elements such that
        # minimum element is at top
        self.min_heap = []
 
    def add(self, val):
 
        # len(max_heap) == 0 or curr_element
        # smaller than max_heap top
        if (len(self.max_heap) == 0 or
            self.max_heap[0] > val):
            push(self.max_heap, -val)
 
        else:
            push(self.min_heap, val)
 
        # If size of max_heap + 1 greater
        # than min_heap
        if (len(self.max_heap)+1 >
            len(self.min_heap)):
            val = pop(self.max_heap)
            push(self.min_heap, -val)
 
        # If size of min_heap
        # greater than max_heap
        if (len(self.min_heap) >
            len(self.max_heap)):
            val = pop(self.min_heap)
            push(self.max_heap, -val)
 
        # Finally if sum of sizes is odd,
        # return median
        if (len(self.min_heap) +
            len(self.max_heap)) % 2 == 1:
            return (-self.max_heap[0])
 
        # Else return 0
        else:
            return 0
 
# Function to calculate the sum
# of all odd length subarrays
def solve(arr):
    ans = 0
     
    # Size of the array
    n = len(arr)
    for i in range(n):
         
        # Create an object
        # of class find_median
        obj = find_median()
        for j in range(i, n, 1):
             
            # Add value to the heaps
            # using object
            val = obj.add(arr[j])
            ans += val
     
    return (ans)
 
# Driver Code
if __name__ == "__main__":
    arr = [4, 2, 5, 1]
    print(solve(arr))


输出
18

时间复杂度 O(N 3 * Log(N))  
辅助空间 O(N)

注意:可以应用插入排序,而不是每次都对数组进行排序,这需要花费 ( N*logN) 。但是,总体时间复杂度仍然是O(N 3 )。

有效方法:排序数组的中位数是将数组中高半部分与低半部分分开的值。为了找出中位数,我们只需要中间元素,而不是整个排序数组。运行整数流中位数的方法可以在这里应用。按照下面提到的步骤

  1. 使用最大和最小堆计算运行中位数。
  2. 遍历数组中的每一个元素。
  3. 在创建新子数组时,将一个元素添加到堆中,如果大小为奇数则返回中值,否则返回 0。
  4. max_heap用于存储下半部分元素,使得最大元素在顶部, min_heap用于存储上半部分元素,使得最小元素在顶部。
  5. 两个堆之间的差异不应大于 1,并且一个额外的元素始终放置在max_heap中。

注意:这里的 max_heap 是使用 min_heap 实现的,只需将值取反,以便可以弹出最大的负元素

下面是上述方法的实现:

Python3

# Python program for the above approach
from heapq import heappush as push, heappop as pop
 
# Find the sum of medians of odd-length
# subarrays
 
 
class find_median():
 
    # Constructor to declare two heaps
    def __init__(self):
 
        # Store lower half elements such that
        # maximum element is at top
        self.max_heap = []
 
        # Store higher half elements such that
        # minimum element is at top
        self.min_heap = []
 
    def add(self, val):
 
        # len(max_heap) == 0 or curr_element
        # smaller than max_heap top
        if (len(self.max_heap) == 0 or
            self.max_heap[0] > val):
            push(self.max_heap, -val)
 
        else:
            push(self.min_heap, val)
 
        # If size of max_heap + 1 greater
        # than min_heap
        if (len(self.max_heap)+1 >
            len(self.min_heap)):
            val = pop(self.max_heap)
            push(self.min_heap, -val)
 
        # If size of min_heap
        # greater than max_heap
        if (len(self.min_heap) >
            len(self.max_heap)):
            val = pop(self.min_heap)
            push(self.max_heap, -val)
 
        # Finally if sum of sizes is odd,
        # return median
        if (len(self.min_heap) +
            len(self.max_heap)) % 2 == 1:
            return (-self.max_heap[0])
 
        # Else return 0
        else:
            return 0
 
# Function to calculate the sum
# of all odd length subarrays
def solve(arr):
    ans = 0
     
    # Size of the array
    n = len(arr)
    for i in range(n):
         
        # Create an object
        # of class find_median
        obj = find_median()
        for j in range(i, n, 1):
             
            # Add value to the heaps
            # using object
            val = obj.add(arr[j])
            ans += val
     
    return (ans)
 
# Driver Code
if __name__ == "__main__":
    arr = [4, 2, 5, 1]
    print(solve(arr))
输出
18

时间复杂度 O(N 2 * Log(N))  
辅助空间 O(N)