📌  相关文章
📜  在小于 O(n) 的时间内查找有限范围数组中每个元素的频率

📅  最后修改于: 2021-09-16 11:11:21             🧑  作者: Mango

给定一个排序的正整数数组,数组中每个元素出现的计数。假设数组中的所有元素都小于某个常数 M。
在不遍历完整数组的情况下执行此操作。即预期的时间复杂度小于 O(n)。

例子:

Input: arr[] = [1, 1, 1, 2, 3, 3, 5,
               5, 8, 8, 8, 9, 9, 10] 
Output:
Element 1 occurs 3 times
Element 2 occurs 1 times
Element 3 occurs 2 times
Element 5 occurs 2 times
Element 8 occurs 3 times
Element 9 occurs 2 times
Element 10 occurs 1 times

Input: arr[] = [2, 2, 6, 6, 7, 7, 7, 11] 
Output:
Element 2 occurs 2 times
Element 6 occurs 2 times
Element 7 occurs 3 times
Element 11 occurs 1 times

方法 1该方法使用线性搜索技术来解决以下问题。

  • 方法:思想是遍历输入数组,对于数组的每个不同元素,将其频率存储在一个HashMap中,最后打印HashMap。
  • 算法:
    1. 创建一个 HashMap 将频率映射到元素,即存储元素频率对。
    2. 从头到尾遍历数组。
    3. 为数组中的每个元素更新频率,即hm[array[i]]++
    4. 遍历HashMap并打印元素频率对。
  • 执行:
C++
// C++ program to count number of occurrences of
// each element in the array #include 
#include 
using namespace std;
 
// It prints number of
// occurrences of each element in the array.
void findFrequency(int arr[], int n)
{
    // HashMap to store frequencies
    unordered_map mp;
 
    // traverse the array
    for (int i = 0; i < n; i++) {
        // update the frequency
        mp[arr[i]]++;
    }
 
    // traverse the hashmap
    for (auto i : mp) {
        cout << "Element " << i.first << " occurs "
             << i.second << " times" << endl;
    }
}
 
// Driver function
int main()
{
    int arr[] = { 1, 1, 1, 2, 3, 3, 5, 5,
                  8, 8, 8, 9, 9, 10 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    findFrequency(arr, n);
 
    return 0;
}


Java
// Java program to count number
// of occurrences of each
// element in the array
import java.io.*;
import java.util.*;
class GFG
{
 
  // It prints number of
  // occurrences of each
  // element in the array.
  static void findFrequency(int [] arr,
                            int n)
  {
    Map mp
      = new HashMap();
 
    // traverse the array
    for (int i = 0; i < n; i++)
    {
 
      // update the frequency
      if (!mp.containsKey(arr[i]))
        mp.put(arr[i],0);
 
      mp.put(arr[i],mp.get(arr[i])+1);
    }
 
    // traverse the hashmap
    for (Map.Entry kvp : mp.entrySet())
    {
      System.out.println("Element " + kvp.getKey() +
                         " occurs " + kvp.getValue() +
                         " times");
    }
  }
 
  // Driver function
  public static void main (String[] args) {
 
 
    int [] arr = {1, 1, 1, 2,
                  3, 3, 5, 5,
                  8, 8, 8, 9,
                  9, 10};
    int n = arr.length;
    findFrequency(arr, n);
  }
}
 
// This code is contributed by avanitrachhadiya2155


Python3
# Python program to count number of occurrences of
# each element in the array #include 
 
# It prints number of
# occurrences of each element in the array.
def findFrequency(arr, n):
     
    # HashMap to store frequencies
    mp = {}
 
    # traverse the array
    for i in range(n):
 
        # update the frequency
        if arr[i] not in mp:
            mp[arr[i]] = 0
        mp[arr[i]] += 1
         
    # traverse the hashmap
    for i in mp:
        print("Element", i, "occurs", mp[i], "times")
     
# Driver function
arr = [1, 1, 1, 2, 3, 3, 5, 5,8, 8, 8, 9, 9, 10]
n = len(arr)
 
findFrequency(arr, n)
     
# This code is contributed by shubhamsingh10


C#
// C# program to count number
// of occurrences of each
// element in the array
using System;
using System.Collections.Generic;
class GFG{
 
// It prints number of
// occurrences of each
// element in the array.
static void findFrequency(int [] arr,
                          int n)
{
  // HashMap to store frequencies
  Dictionary  mp =
              new Dictionary();
 
  // traverse the array
  for (int i = 0; i < n; i++)
  {
    // update the frequency
    if (!mp.ContainsKey(arr[i]))
      mp[arr[i]] = 0;
 
    mp[arr[i]]++;
  }
 
  // traverse the hashmap
  foreach(KeyValuePair kvp in mp)
    Console.WriteLine("Element " + kvp.Key +
                      " occurs " + kvp.Value +
                      " times");
}
 
// Driver function
public static void Main()
{
  int [] arr = {1, 1, 1, 2,
                3, 3, 5, 5,
                8, 8, 8, 9,
                9, 10};
  int n = arr.Length;
  findFrequency(arr, n);
}
}
 
// This code is contributed by Chitranayal


Javascript


C++
// C++ program to count number of occurrences of
// each element in the array in less than O(n) time
#include 
#include 
using namespace std;
 
// A recursive function to count number of occurrences
// for each element in the array without traversing
// the whole array
void findFrequencyUtil(int arr[], int low, int high,
                       vector& freq)
{
    // If element at index low is equal to element
    // at index high in the array
    if (arr[low] == arr[high]) {
        // increment the frequency of the element
        // by count of elements between high and low
        freq[arr[low]] += high - low + 1;
    }
    else {
        // Find mid and recurse for left and right
        // subarray
        int mid = (low + high) / 2;
        findFrequencyUtil(arr, low, mid, freq);
        findFrequencyUtil(arr, mid + 1, high, freq);
    }
}
 
// A wrapper over recursive function
// findFrequencyUtil(). It print number of
// occurrences of each element in the array.
void findFrequency(int arr[], int n)
{
    // create a empty vector to store frequencies
    // and initialize it by 0. Size of vector is
    // maximum value (which is last value in sorted
    // array) plus 1.
    vector freq(arr[n - 1] + 1, 0);
 
    // Fill the vector with frequency
    findFrequencyUtil(arr, 0, n - 1, freq);
 
    // Print the frequencies
    for (int i = 0; i <= arr[n - 1]; i++)
        if (freq[i] != 0)
            cout << "Element " << i << " occurs "
                 << freq[i] << " times" << endl;
}
 
// Driver function
int main()
{
    int arr[] = { 1, 1, 1, 2, 3, 3, 5, 5,
                  8, 8, 8, 9, 9, 10 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    findFrequency(arr, n);
 
    return 0;
}


Java
// Java program to count number of occurrences of
// each element in the array in less than O(n) time
import java.util.*;
 
class GFG {
 
    // A recursive function to count number of occurrences
    // for each element in the array without traversing
    // the whole array
    static void findFrequencyUtil(int arr[], int low,
                                  int high, int[] freq)
    {
        // If element at index low is equal to element
        // at index high in the array
        if (arr[low] == arr[high]) {
            // increment the frequency of the element
            // by count of elements between high and low
            freq[arr[low]] += high - low + 1;
        }
        else {
            // Find mid and recurse for left and right
            // subarray
            int mid = (low + high) / 2;
            findFrequencyUtil(arr, low, mid, freq);
            findFrequencyUtil(arr, mid + 1, high, freq);
        }
    }
 
    // A wrapper over recursive function
    // findFrequencyUtil(). It print number of
    // occurrences of each element in the array.
    static void findFrequency(int arr[], int n)
    {
        // create a empty vector to store frequencies
        // and initialize it by 0. Size of vector is
        // maximum value (which is last value in sorted
        // array) plus 1.
        int[] freq = new int[arr[n - 1] + 1];
 
        // Fill the vector with frequency
        findFrequencyUtil(arr, 0, n - 1, freq);
 
        // Print the frequencies
        for (int i = 0; i <= arr[n - 1]; i++)
            if (freq[i] != 0)
                System.out.println("Element " + i + " occurs " + freq[i] + " times");
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 1, 1, 1, 2, 3, 3, 5,
                      5, 8, 8, 8, 9, 9, 10 };
        int n = arr.length;
 
        findFrequency(arr, n);
    }
}
 
// This code is contributed by 29AjayKumar


Python3
# Python 3 program to count number of occurrences of
# each element in the array in less than O(n) time
 
# A recursive function to count number of occurrences
# for each element in the array without traversing
# the whole array
def findFrequencyUtil(arr, low, high, freq):
     
    # If element at index low is equal to element
    # at index high in the array
    if (arr[low] == arr[high]):
         
        # increment the frequency of the element
        # by count of elements between high and low
        freq[arr[low]] += high - low + 1
     
    else:
         
        # Find mid and recurse for left 
        # and right subarray
        mid = int((low + high) / 2)
        findFrequencyUtil(arr, low, mid, freq)
        findFrequencyUtil(arr, mid + 1, high, freq)
     
# A wrapper over recursive function
# findFrequencyUtil(). It print number of
# occurrences of each element in the array.
def findFrequency(arr, n):
     
    # create a empty vector to store frequencies
    # and initialize it by 0. Size of vector is
    # maximum value (which is last value in sorted
    # array) plus 1.
    freq = [0 for i in range(n - 1 + 1)]
     
    # Fill the vector with frequency
    findFrequencyUtil(arr, 0, n - 1, freq)
 
    # Print the frequencies
    for i in range(0, arr[n - 1] + 1, 1):
        if (freq[i] != 0):
            print("Element", i, "occurs",
                        freq[i], "times")
 
# Driver Code
if __name__ == '__main__':
    arr = [1, 1, 1, 2, 3, 3, 5,
           5, 8, 8, 8, 9, 9, 10]
    n = len(arr)
    findFrequency(arr, n)
     
# This code is contributed by
# Surendra_Gangwar


C#
// C# program to count number of occurrences of
// each element in the array in less than O(n) time
using System;
 
class GFG {
 
    // A recursive function to count number of occurrences
    // for each element in the array without traversing
    // the whole array
    static void findFrequencyUtil(int[] arr, int low,
                                  int high, int[] freq)
    {
        // If element at index low is equal to element
        // at index high in the array
        if (arr[low] == arr[high]) {
            // increment the frequency of the element
            // by count of elements between high and low
            freq[arr[low]] += high - low + 1;
        }
        else {
            // Find mid and recurse for left and right
            // subarray
            int mid = (low + high) / 2;
            findFrequencyUtil(arr, low, mid, freq);
            findFrequencyUtil(arr, mid + 1, high, freq);
        }
    }
 
    // A wrapper over recursive function
    // findFrequencyUtil(). It print number of
    // occurrences of each element in the array.
    static void findFrequency(int[] arr, int n)
    {
        // create a empty vector to store frequencies
        // and initialize it by 0. Size of vector is
        // maximum value (which is last value in sorted
        // array) plus 1.
        int[] freq = new int[arr[n - 1] + 1];
 
        // Fill the vector with frequency
        findFrequencyUtil(arr, 0, n - 1, freq);
 
        // Print the frequencies
        for (int i = 0; i <= arr[n - 1]; i++)
            if (freq[i] != 0)
                Console.WriteLine("Element " + i + " occurs " + freq[i] + " times");
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int[] arr = { 1, 1, 1, 2, 3, 3, 5,
                      5, 8, 8, 8, 9, 9, 10 };
        int n = arr.Length;
 
        findFrequency(arr, n);
    }
}
 
// This code is contributed by Princi Singh


Javascript


  • 输出:
Element 1 occurs 3 times
Element 2 occurs 1 times
Element 3 occurs 2 times
Element 5 occurs 2 times
Element 8 occurs 3 times
Element 9 occurs 2 times
Element 10 occurs 1 times
  • 复杂度分析:
    • 时间复杂度: O(n),只需要遍历一次数组。
    • 空间复杂度: O(n),在HashMap中存储元素需要O(n)额外的空间。

方法 2该方法使用二分搜索技术得出解决方案。

  • 方法:如果所有元素都被排序,问题可以在小于 O(n) 的时间内解决,即如果数组中存在相似的元素,那么这些元素在一个连续的子数组中,或者可以说如果一个子数组的两端是相同则子数组内的所有元素都相等。因此,该元素的计数是子数组的大小,不需要计算该子数组的所有元素。
  • 算法:
    1. 创建一个 HashMap ( hm ) 来存储元素的频率。
    2. 创建一个接受数组和大小的递归函数。
    3. 检查数组的第一个元素是否等于最后一个元素。如果相等,则所有元素都相同,并通过hm[array[0]+=size更新频率
    4. 否则将数组分成相等的两半,并为两半递归调用该函数。
    5. 遍历hashmap并打印元素频率对。
  • 执行:

C++

// C++ program to count number of occurrences of
// each element in the array in less than O(n) time
#include 
#include 
using namespace std;
 
// A recursive function to count number of occurrences
// for each element in the array without traversing
// the whole array
void findFrequencyUtil(int arr[], int low, int high,
                       vector& freq)
{
    // If element at index low is equal to element
    // at index high in the array
    if (arr[low] == arr[high]) {
        // increment the frequency of the element
        // by count of elements between high and low
        freq[arr[low]] += high - low + 1;
    }
    else {
        // Find mid and recurse for left and right
        // subarray
        int mid = (low + high) / 2;
        findFrequencyUtil(arr, low, mid, freq);
        findFrequencyUtil(arr, mid + 1, high, freq);
    }
}
 
// A wrapper over recursive function
// findFrequencyUtil(). It print number of
// occurrences of each element in the array.
void findFrequency(int arr[], int n)
{
    // create a empty vector to store frequencies
    // and initialize it by 0. Size of vector is
    // maximum value (which is last value in sorted
    // array) plus 1.
    vector freq(arr[n - 1] + 1, 0);
 
    // Fill the vector with frequency
    findFrequencyUtil(arr, 0, n - 1, freq);
 
    // Print the frequencies
    for (int i = 0; i <= arr[n - 1]; i++)
        if (freq[i] != 0)
            cout << "Element " << i << " occurs "
                 << freq[i] << " times" << endl;
}
 
// Driver function
int main()
{
    int arr[] = { 1, 1, 1, 2, 3, 3, 5, 5,
                  8, 8, 8, 9, 9, 10 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    findFrequency(arr, n);
 
    return 0;
}

Java

// Java program to count number of occurrences of
// each element in the array in less than O(n) time
import java.util.*;
 
class GFG {
 
    // A recursive function to count number of occurrences
    // for each element in the array without traversing
    // the whole array
    static void findFrequencyUtil(int arr[], int low,
                                  int high, int[] freq)
    {
        // If element at index low is equal to element
        // at index high in the array
        if (arr[low] == arr[high]) {
            // increment the frequency of the element
            // by count of elements between high and low
            freq[arr[low]] += high - low + 1;
        }
        else {
            // Find mid and recurse for left and right
            // subarray
            int mid = (low + high) / 2;
            findFrequencyUtil(arr, low, mid, freq);
            findFrequencyUtil(arr, mid + 1, high, freq);
        }
    }
 
    // A wrapper over recursive function
    // findFrequencyUtil(). It print number of
    // occurrences of each element in the array.
    static void findFrequency(int arr[], int n)
    {
        // create a empty vector to store frequencies
        // and initialize it by 0. Size of vector is
        // maximum value (which is last value in sorted
        // array) plus 1.
        int[] freq = new int[arr[n - 1] + 1];
 
        // Fill the vector with frequency
        findFrequencyUtil(arr, 0, n - 1, freq);
 
        // Print the frequencies
        for (int i = 0; i <= arr[n - 1]; i++)
            if (freq[i] != 0)
                System.out.println("Element " + i + " occurs " + freq[i] + " times");
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 1, 1, 1, 2, 3, 3, 5,
                      5, 8, 8, 8, 9, 9, 10 };
        int n = arr.length;
 
        findFrequency(arr, n);
    }
}
 
// This code is contributed by 29AjayKumar

蟒蛇3

# Python 3 program to count number of occurrences of
# each element in the array in less than O(n) time
 
# A recursive function to count number of occurrences
# for each element in the array without traversing
# the whole array
def findFrequencyUtil(arr, low, high, freq):
     
    # If element at index low is equal to element
    # at index high in the array
    if (arr[low] == arr[high]):
         
        # increment the frequency of the element
        # by count of elements between high and low
        freq[arr[low]] += high - low + 1
     
    else:
         
        # Find mid and recurse for left 
        # and right subarray
        mid = int((low + high) / 2)
        findFrequencyUtil(arr, low, mid, freq)
        findFrequencyUtil(arr, mid + 1, high, freq)
     
# A wrapper over recursive function
# findFrequencyUtil(). It print number of
# occurrences of each element in the array.
def findFrequency(arr, n):
     
    # create a empty vector to store frequencies
    # and initialize it by 0. Size of vector is
    # maximum value (which is last value in sorted
    # array) plus 1.
    freq = [0 for i in range(n - 1 + 1)]
     
    # Fill the vector with frequency
    findFrequencyUtil(arr, 0, n - 1, freq)
 
    # Print the frequencies
    for i in range(0, arr[n - 1] + 1, 1):
        if (freq[i] != 0):
            print("Element", i, "occurs",
                        freq[i], "times")
 
# Driver Code
if __name__ == '__main__':
    arr = [1, 1, 1, 2, 3, 3, 5,
           5, 8, 8, 8, 9, 9, 10]
    n = len(arr)
    findFrequency(arr, n)
     
# This code is contributed by
# Surendra_Gangwar

C#

// C# program to count number of occurrences of
// each element in the array in less than O(n) time
using System;
 
class GFG {
 
    // A recursive function to count number of occurrences
    // for each element in the array without traversing
    // the whole array
    static void findFrequencyUtil(int[] arr, int low,
                                  int high, int[] freq)
    {
        // If element at index low is equal to element
        // at index high in the array
        if (arr[low] == arr[high]) {
            // increment the frequency of the element
            // by count of elements between high and low
            freq[arr[low]] += high - low + 1;
        }
        else {
            // Find mid and recurse for left and right
            // subarray
            int mid = (low + high) / 2;
            findFrequencyUtil(arr, low, mid, freq);
            findFrequencyUtil(arr, mid + 1, high, freq);
        }
    }
 
    // A wrapper over recursive function
    // findFrequencyUtil(). It print number of
    // occurrences of each element in the array.
    static void findFrequency(int[] arr, int n)
    {
        // create a empty vector to store frequencies
        // and initialize it by 0. Size of vector is
        // maximum value (which is last value in sorted
        // array) plus 1.
        int[] freq = new int[arr[n - 1] + 1];
 
        // Fill the vector with frequency
        findFrequencyUtil(arr, 0, n - 1, freq);
 
        // Print the frequencies
        for (int i = 0; i <= arr[n - 1]; i++)
            if (freq[i] != 0)
                Console.WriteLine("Element " + i + " occurs " + freq[i] + " times");
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int[] arr = { 1, 1, 1, 2, 3, 3, 5,
                      5, 8, 8, 8, 9, 9, 10 };
        int n = arr.Length;
 
        findFrequency(arr, n);
    }
}
 
// This code is contributed by Princi Singh

Javascript


  • 输出:
Element 1 occurs 3 times
Element 2 occurs 1 times
Element 3 occurs 2 times
Element 5 occurs 2 times
Element 8 occurs 3 times
Element 9 occurs 2 times
Element 10 occurs 1 times
  • 复杂度分析:
    • 时间复杂度: O(m log n)。
      其中 m 是大小为 n 的数组中不同元素的数量。由于 m <= M(一个常数)(元素在有限范围内),这个解的时间复杂度是 O(log n)。
    • 空间复杂度: O(n)。
      将元素存储在 HashMap 中需要 O(n) 额外空间。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程