📌  相关文章
📜  计算具有至少K个元素的子数组至少出现两次

📅  最后修改于: 2021-05-14 00:28:20             🧑  作者: Mango

给定一个由N个整数和一个正整数K组成的数组arr [] ,任务是计算具有正好K个元素至少出现两次的子数组的数量。

例子:

天真的方法:解决此问题的最简单方法是从给定数组生成所有可能的子数组 并计算至少有两次恰好有K个元素的子数组。检查完所有子阵列后,打印获得的子阵列总数。

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

高效的方法:可以通过使用哈希和两个指针技术来优化上述方法。请按照以下步骤解决问题:

  • 初始化一个变量,例如cntSub0 ,以存储所有K元素至少出现两次的所有可能子数组的计数。
  • 初始化两个变量,将l设为0 ,将r设为0 ,以分别存储每个子数组的左边界和右边界的索引。
  • 初始化一个Map(例如mp )和一个Set(例如S)以将元素计数存储在子数组中,并存储其频率至少为2的元素。
  • 迭代直到r小于N并执行以下操作:
    • r小于N且集合的大小最大为K时进行迭代:
      • 如果mp [arr [r]]等于2则以mp为单位增加arr [r]的计数,然后将其推入集合S中
      • r递增1
      • 如果集合S的大小为K ,则将cntSub增大1
    • l 并且集合的大小大于K时进行迭代:
      • 如果mp [arr [r]]等于1则以mp为单位减少arr [l]的计数,然后从集合S中删除该元素。
      • cntSubl1
  • 现在,当l 且集合的大小为K时进行迭代,并将arr [l]的计数减1 ,如果arr [l]的频率为1 ,则从集合中删除arr [l]
  • 完成上述步骤后,打印cntSub的值作为子数组的结果计数。

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count the subarrays with
// exactly K elements occuring twice
int cntSubarrays(int A[], int K, int n)
{
    // Stores the count of subarrays
    // having exactly K elements
    // occuring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    map mp;
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    set st;
 
    // Iterate while r < n
    while (r < n) {
 
        // Iterate while r < n
        // and size of st <= K
        while (r < n && st.size() <= K) {
 
            // If mp[A[r]] >= 1
            if (mp[A[r]]) {
                st.insert(A[r]);
            }
 
            // Increment count of A[r]
            mp[A[r]]++;
 
            // Increment r by 1
            r++;
 
            // If st.size() is K
            if (st.size() == K)
                cntSub++;
        }
 
        // Iterate while l < r
        // and st.size() > K
        while (l < r && st.size() > K) {
 
            // Increment cntSub by 1
            cntSub++;
 
            // Decrement cntSub by 1
            mp[A[l]]--;
 
            // If mp[A[l]] = 1
            if (mp[A[l]] == 1) {
                st.erase(st.find(A[l]));
            }
 
            // Increment l by 1
            l++;
        }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.size() == K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        mp[A[l]]--;
 
        // If Mp[A[l]] is equal to 1
        if (mp[A[l]] == 1) {
            st.erase(st.find(A[l]));
        }
 
        // Increment l by 1
        l++;
    }
 
    // Return cntSub
    return cntSub;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << cntSubarrays(arr, K, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG {
 
  // Function to count the subarrays with
  // exactly K elements occuring twice
  static int cntSubarrays(int[] A, int K, int n)
  {
 
    // Stores the count of subarrays
    // having exactly K elements
    // occuring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    HashMap mp
      = new HashMap();
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    HashSet st = new HashSet();
 
    // Iterate while r < n
    while (r < n) {
 
      // Iterate while r < n
      // and size of st <= K
      while (r < n && st.size() <= K) {
 
        // If mp[A[r]] >= 1
        if (mp.containsKey(A[r])) {
          st.add(A[r]);
        }
 
        // Increment count of A[r]
        if (mp.containsKey(A[r]))
          mp.put(A[r], mp.get(A[r]) + 1);
        else
          mp.put(A[r], 1);
 
        // Increment r by 1
        r++;
 
        // If st.size() is K
        if (st.size() == K)
          cntSub++;
      }
 
      // Iterate while l < r
      // and st.size() > K
      while (l < r && st.size() > K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        // Decrement cntSub by 1
        if (mp.containsKey(A[l]))
          mp.put(A[l], mp.get(A[l]) - 1);
 
        // If mp[A[l]] = 1
        if (mp.get(A[l]) == 1) {
          st.remove(A[l]);
        }
 
        // Increment l by 1
        l++;
      }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.size() == K) {
 
      // Increment cntSub by 1
      cntSub++;
      if (mp.containsKey(A[l]))
        mp.put(A[l], mp.get(A[l]) - 1);
 
      // If Mp[A[l]] is equal to 1
      if (mp.get(A[l]) == 1) {
        st.remove(A[l]);
      }
 
      // Increment l by 1
      l++;
    }
 
    // Return cntSub
    return cntSub;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int[] arr = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = arr.length;
 
    System.out.println(cntSubarrays(arr, K, N));
  }
}
 
// This code is contributed by ukasp.


Python3
# Python3 program for the above approach
 
# Function to count the subarrays with
# exactly K elements occuring twice
def cntSubarrays(A, K, n):
     
    # Stores the count of subarrays
    # having exactly K elements
    # occuring at least twice
    cntSub = 0
 
    # Stores the count of
    # integers in the subarray
    mp = {}
 
    # Stores the indices of left
    # boundary and right boundary
    l = 0
    r = 0
 
    # Store the elements which occurs
    # atleast twice between [l, r]
    st = set()
 
    # Iterate while r < n
    while (r < n):
         
        # Iterate while r < n
        # and size of st <= K
        while (r < n and len(st) <= K):
             
            # If mp[A[r]] >= 1
            if (A[r] in mp):
                st.add(A[r])
 
            # Increment count of A[r]
            if (A[r] in mp):
                mp[A[r]] += 1
            else:
                mp[A[r]] = 1
 
            # Increment r by 1
            r += 1
 
            # If st.size() is K
            if (len(st) == K):
                cntSub += 1
 
        # Iterate while l < r
        # and st.size() > K
        while (l < r and len(st) > K):
             
            # Increment cntSub by 1
            cntSub += 1
 
            # Decrement cntSub by 1
            if (A[l] in mp):
                mp[A[l]] -= 1
            else:
                mp[A[l]] = 1
  
            # If mp[A[l]] = 1
            if (mp[A[l]] == 1):
                st.remove(A[l])
 
            # Increment l by 1
            l += 1
 
    # Iterate while l < n  and
    # st.size() == K
    while (l < n and len(st) == K):
         
        # Increment cntSub by 1
        cntSub += 1
 
        mp[A[l]] -= 1
 
        # If Mp[A[l]] is equal to 1
        if (mp[A[l]] == 1):
            st.remove(A[l])
 
        # Increment l by 1
        l += 1
 
    # Return cntSub
    return cntSub
 
# Driver Code
if __name__ == '__main__':
     
    arr =  [1, 1, 1, 2, 2]
    K = 1
    N = len(arr)
     
    print(cntSubarrays(arr, K, N))
 
# This code is contributed by ipg2016107


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
  // Function to count the subarrays with
  // exactly K elements occuring twice
  static int cntSubarrays(int []A, int K, int n)
  {
     
    // Stores the count of subarrays
    // having exactly K elements
    // occuring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    Dictionary mp = new Dictionary();
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    HashSet st = new HashSet();
 
    // Iterate while r < n
    while (r < n) {
 
      // Iterate while r < n
      // and size of st <= K
      while (r < n && st.Count <= K) {
 
        // If mp[A[r]] >= 1
        if (mp.ContainsKey(A[r])) {
          st.Add(A[r]);
        }
 
        // Increment count of A[r]
        if (mp.ContainsKey(A[r]))
          mp[A[r]]++;
        else
          mp[A[r]] = 1;
 
        // Increment r by 1
        r++;
 
        // If st.size() is K
        if (st.Count == K)
          cntSub++;
      }
 
      // Iterate while l < r
      // and st.size() > K
      while (l < r && st.Count > K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        // Decrement cntSub by 1
        if (mp.ContainsKey(A[l]))
          mp[A[l]]--;
 
        // If mp[A[l]] = 1
        if (mp[A[l]] == 1) {
          st.Remove(A[l]);
        }
 
        // Increment l by 1
        l++;
      }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.Count == K) {
 
      // Increment cntSub by 1
      cntSub++;
      if (mp.ContainsKey(A[l]))
        mp[A[l]]--;
 
      // If Mp[A[l]] is equal to 1
      if (mp[A[l]] == 1) {
        st.Remove(A[l]);
      }
 
      // Increment l by 1
      l++;
    }
 
    // Return cntSub
    return cntSub;
  }
 
  // Driver Code
  public static void Main()
  {
    int []arr = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = arr.Length;
 
    Console.WriteLine(cntSubarrays(arr, K, N));
  }
}
 
// This code is contributed by ipg2016107.


输出:
7

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