Find the maximum length of the prefix | Set-2 - GeeksforGeeks

15 Jul, 2021
Given an array arr[] of N integers, the task is to find the maximum prefix length of the array such that removing exactly one element from the prefix will make the frequency of the remaining prefix elements the same.
Examples:  
Input: arr[] = {1, 1, 1, 2, 2, 2}  Output: 5  Explanation: The following prefixes satisfy the given conditions:
The prefix over the range [0, 0]. Removing the only element in the prefix will become empty.The prefix over the range [0, 1]. Removing either of the element from the prefix, frequency of every element will becomes equal in the prefix.The prefix over the range [0, 2]. Removing any of the element from the prefix, frequency of every element will becomes equal in the prefix.The prefix over the range [0, 3]. Removing the element at index 3 from the prefix, frequency of every element will becomes equal in the prefix.The prefix over the range [0, 4]. Removing any element in the range [0, 2] from the prefix, frequency of every element will becomes equal in the prefix.
The prefix over the range [0, 0]. Removing the only element in the prefix will become empty.
The prefix over the range [0, 1]. Removing either of the element from the prefix, frequency of every element will becomes equal in the prefix.
The prefix over the range [0, 2]. Removing any of the element from the prefix, frequency of every element will becomes equal in the prefix.
The prefix over the range [0, 3]. Removing the element at index 3 from the prefix, frequency of every element will becomes equal in the prefix.
The prefix over the range [0, 4]. Removing any element in the range [0, 2] from the prefix, frequency of every element will becomes equal in the prefix.
Therefore, the maximum length of prefix satisfying the conditions is 5.
Input: arr[] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5}  Output: 13 
The Hashing and sorting-based approach has been discussed in Set 1 of this article.
Approach: The idea is to use two Maps to keep track of the frequencies of elements and use the following four conditions to check for valid prefixes.
Frequencies of all the elements of the prefix are equal to 1.All the elements in the prefix window are the same.There exist only two distinct frequencies of the elements in the prefix and the difference between them is equal to 1 and the count of the frequency with a larger value is 1.There exists a single element with frequency 1 and except that all elements have the same frequency.
Frequencies of all the elements of the prefix are equal to 1.
All the elements in the prefix window are the same.
There exist only two distinct frequencies of the elements in the prefix and the difference between them is equal to 1 and the count of the frequency with a larger value is 1.
There exists a single element with frequency 1 and except that all elements have the same frequency.
Follow the steps below to solve the problem:
Initialize two Maps say mp1 and mp2 to store the frequency of elements in the prefix and to store the frequency of the frequencies of the elements respectively.
Also, Initialize a variable say ans as 0 to store the maximum length of the prefix.
Traverse over the range [0, N-1] using the variable i and follow the below steps:If the count of arr[i] is not equal to 0, then decrement the count of that frequency from the map mp2 and if it becomes 0 then erase the value from map mp2.Increment the count of arr[i] in the map mp1 by 1 and then increment the count of the new frequency of arr[i] i.e mp1[arr[i]] in Map mp2 by 1.If the count of the current element is equal to its prefix length i.e (i+1) or every element occurred once in the prefix then update the value of ans to max(ans, i+1).Now, if the size of mp2 is equal to 2 then perform the following steps,Store the frequencies of the array element i.e key of the map mp2 in variables say freq1 and freq2 respectively.Store the counts of frequencies of freq1 and freq2 in variables say count1 and count2.Check if the difference between freq2 and freq1 is equal to 1 and the value of count2 is equal to 1 then update the ans to max(ans, i+1).Else, if the difference between freq1 and freq2 is equal to 1 and the value of count1 is equal to 1 then update the ans to max(ans, i+1).Else if freq2 and count2 are equal to 1 or freq1 and count1 are equal to 1 then update the ans to max(ans, i+1).
If the count of arr[i] is not equal to 0, then decrement the count of that frequency from the map mp2 and if it becomes 0 then erase the value from map mp2.
Increment the count of arr[i] in the map mp1 by 1 and then increment the count of the new frequency of arr[i] i.e mp1[arr[i]] in Map mp2 by 1.
If the count of the current element is equal to its prefix length i.e (i+1) or every element occurred once in the prefix then update the value of ans to max(ans, i+1).
Now, if the size of mp2 is equal to 2 then perform the following steps,Store the frequencies of the array element i.e key of the map mp2 in variables say freq1 and freq2 respectively.Store the counts of frequencies of freq1 and freq2 in variables say count1 and count2.Check if the difference between freq2 and freq1 is equal to 1 and the value of count2 is equal to 1 then update the ans to max(ans, i+1).Else, if the difference between freq1 and freq2 is equal to 1 and the value of count1 is equal to 1 then update the ans to max(ans, i+1).Else if freq2 and count2 are equal to 1 or freq1 and count1 are equal to 1 then update the ans to max(ans, i+1).
Store the frequencies of the array element i.e key of the map mp2 in variables say freq1 and freq2 respectively.
Store the counts of frequencies of freq1 and freq2 in variables say count1 and count2.
Check if the difference between freq2 and freq1 is equal to 1 and the value of count2 is equal to 1 then update the ans to max(ans, i+1).
Else, if the difference between freq1 and freq2 is equal to 1 and the value of count1 is equal to 1 then update the ans to max(ans, i+1).
Else if freq2 and count2 are equal to 1 or freq1 and count1 are equal to 1 then update the ans to max(ans, i+1).
Finally, after completing the above steps print the value of ans.
Below is the implementation of the above approach:
C++
Java
Python3
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // Function to find the maximum// length of the required prefixint maxPrefixLen(int arr[], int N){     // Stores the frequency of    // elements    unordered_map<int, int> a, b;     // Stores the maximum length    // of the prefix satisfying    // the conditions    int ans = 1;     // Traverse the array arr[]    for (int i = 0; i < N; i++) {         // Stores the count of        // current element        int curr = a[arr[i]];         // If curr is not        // equal to 0        if (curr != 0) {             // Decrement b[curr]            // by 1            b[curr]--;             // If b[curr] is 0            if (b[curr] == 0) {                // Remove b[curr]                // from the b                b.erase(curr);            }        }         // Update        a[arr[i]]++;        b[curr + 1]++;         // If all elements in the        // prefix are same or if        // all elements have frequency        // 1        if (a[arr[i]] == i + 1            or (b.find(1) != b.end() and b[1] == i + 1)) {            // Update the value of ans            ans = max(ans, i + 1);        }         // Else if the size of b        // is 2        else if (b.size() == 2) {             auto p = b.begin();            auto q = p;             // Increment q by 1            q++;             int freq1 = p->first;            int freq2 = q->first;             int count1 = p->second;            int count2 = q->second;             // If difference between            // freq2 and freq1 is            // equal to 1 and if            // count2 is equal to 1            if (freq2 - freq1 == 1 and count2 == 1) {                // Update the value                // of ans                ans = max(ans, i + 1);            }             // If difference between            // freq1 and freq2 is            // equal to 1 and if            // count1 is equal to 1            else if (freq1 - freq2 == 1 and count1 == 1) {                // Update the value                // of ans                ans = max(ans, i + 1);            }            // If freq2 and count2 is 1            // or freq1 and count1 is 1            if ((freq2 == 1 and count2 == 1)                or (freq1 == 1 and count1 == 1)) {                // Update the value of                // ans                ans = max(ans, i + 1);            }        }    }     // Return ans    return ans;} // Driver Codeint main(){     int arr[] = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5 };    int N = sizeof(arr) / sizeof(arr[0]);     cout << maxPrefixLen(arr, N);}
// Java program for the above approachimport java.util.HashMap;class GFG {     // Function to find the maximum    // length of the required prefix    public static int maxPrefixLen(int arr[], int N)    {         // Stores the frequency of        // elements        HashMap<Integer, Integer> a = new HashMap<Integer, Integer>();        HashMap<Integer, Integer> b = new HashMap<Integer, Integer>();         // Stores the maximum length        // of the prefix satisfying        // the conditions        int ans = 1;         // Traverse the array arr[]        for (int i = 0; i < N; i++) {             // Stores the count of            // current element            int curr = !a.containsKey(arr[i]) ? 0 : a.get(arr[i]);             // If curr is not            // equal to 0            if (curr != 0) {                 // Decrement b[curr]                // by 1                b.put(curr, b.get(curr) - 1);                 // If b[curr] is 0                if (b.get(curr) == 0)                {                                       // Remove b[curr]                    // from the b                    b.remove(curr);                }            }             // Update            if (a.containsKey(arr[i])) {                a.put(arr[i], a.get(arr[i]) + 1);            } else {                a.put(arr[i], 1);            }             if (b.containsKey(curr + 1)) {                b.put(curr + 1, b.get(curr + 1) + 1);            } else {                b.put(curr + 1, 1);            }             // If all elements in the            // prefix are same or if            // all elements have frequency            // 1            if (a.get(arr[i]) == i + 1 || (b.containsKey(1) && b.get(1) == i + 1))            {                               // Update the value of ans                ans = Math.max(ans, i + 1);            }             else if (b.size() == 2) {                 int p = b.keySet().toArray()[0].hashCode();                int q = b.keySet().toArray()[1].hashCode();                 // Increment q by 1                 int freq1 = p;                int freq2 = q;                 int count1 = b.get(p);                int count2 = b.get(q);                 // If difference between                // freq2 and freq1 is                // equal to 1 and if                // count2 is equal to 1                if ((freq2 - freq1) == 1 && count2 == 1)                {                                       // Update the value                    // of ans                    ans = Math.max(ans, i + 1);                }                 // If difference between                // freq1 and freq2 is                // equal to 1 and if                // count1 is equal to 1                else if (freq1 - freq2 == 1 && count1 == 1)                {                                       // Update the value                    // of ans                    ans = Math.max(ans, i + 1);                }                // If freq2 and count2 is 1                // or freq1 and count1 is 1                if ((freq2 == 1 && count2 == 1) || (freq1 == 1 && count1 == 1))                {                                       // Update the value of                    // ans                    ans = Math.max(ans, i + 1);                }            }        }               // Return ans        return ans;    }     // Driver Code    public static void main(String args[]) {         int arr[] = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5 };        int N = arr.length;         System.out.println(maxPrefixLen(arr, N));    }} // This code is contributed by gfgking.
# Python3 program for the above approach # Function to find the maximum# length of the required prefixdef maxPrefixLen(arr, N):     # Stores the frequency of    # elements    a, b = {}, {}     # Stores the maximum length    # of the prefix satisfying    # the conditions    ans = 1     # Traverse the array arr[]    for i in range(N):                 # Stores the count of        # current element        curr = 0 if (arr[i] not in a) else a[arr[i]]         # If curr is not        # equal to 0        if (curr != 0):                         # Decrement b[curr]            # by 1            b[curr] -= 1                         # If b[curr] is 0            if (b[curr] == 0):                                 # Remove b[curr]                # from the b                del b[curr]         # Update        a[arr[i]] = a.get(arr[i], 0) + 1        b[curr + 1] = b.get(curr + 1, 0) + 1          # If all elements in the        # prefix are same or if        # all elements have frequency        # 1        if (a[arr[i]] == i + 1 or           (1 in b) and b[1] == i + 1):                            # Update the value of ans            ans = max(ans, i + 1)         # Else if the size of b        # is 2        elif (len(b) == 2):            p = list(b.keys())[0]            q = list(b.keys())[1]             freq1 = p            freq2 = q             count1 = b[p]            count2 = b[q]                         # If difference between            # freq2 and freq1 is            # equal to 1 and if            # count2 is equal to 1            if (freq2 - freq1 == 1 and count2 == 1):                                 # Update the value                # of ans                ans = max(ans, i + 1)             # If difference between            # freq1 and freq2 is            # equal to 1 and if            # count1 is equal to 1            elif (freq1 - freq2 == 1 and count1 == 1):                                 # Update the value                # of ans                ans = max(ans, i + 1)                             # If freq2 and count2 is 1            # or freq1 and count1 is 1            if ((freq2 == 1 and count2 == 1) or                (freq1 == 1 and count1 == 1)):                                     # Update the value of                # ans                ans = max(ans, i + 1)     # Return ans    return ans # Driver Codeif __name__ == '__main__':         arr = [ 1, 1, 1, 2, 2, 2, 3,            3, 3, 4, 4, 4, 5 ]    N = len(arr)     print(maxPrefixLen(arr, N)) # This code is contributed by mohit kumar 29
<script>// Javascript program for the above approach // Function to find the maximum// length of the required prefixfunction maxPrefixLen(arr, N) {     // Stores the frequency of    // elements    let a = new Map();    let b = new Map();     // Stores the maximum length    // of the prefix satisfying    // the conditions    let ans = 1     // Traverse the array arr[]    for (let i = 0; i < N; i++) {         // Stores the count of        // current element        let curr = !(a.has(arr[i])) ? 0 : a.get(arr[i])         // If curr is not        // equal to 0        if (curr != 0) {             // Decrement b[curr]            // by 1            b.set(curr, b.get(curr) - 1)             // If b[curr] is 0            if (b.get(curr) == 0) {                 // Remove b[curr]                // from the b                b.delete(curr)            }        }        // Update        if (a.has(arr[i])) {            a.set(arr[i], a.get(arr[i]) + 1)        } else {            a.set(arr[i], 1)        }        if (b.has(curr + 1)) {            b.set(curr + 1, b.get(curr + 1) + 1)        } else {            b.set(curr + 1, 1)        }         // If all elements in the        // prefix are same or if        // all elements have frequency        // 1        if (a.get(arr[i]) == i + 1 ||            (b.has(1)) && b.get(1) == i + 1) {             // Update the value of ans            ans = Math.max(ans, i + 1)             // Else if the size of b            // is 2        }        else if (b.size == 2) {            let p = [...b.keys()][0]            let q = [...b.keys()][1]             let freq1 = p            let freq2 = q             let count1 = b.get(p)            let count2 = b.get(q)             // If difference between            // freq2 and freq1 is            // equal to 1 and if            // count2 is equal to 1            if (freq2 - freq1 == 1 && count2 == 1) {                 // Update the value                // of ans                ans = Math.max(ans, i + 1)            }             // If difference between            // freq1 and freq2 is            // equal to 1 and if            // count1 is equal to 1            else if (freq1 - freq2 == 1 && count1 == 1) {                 // Update the value                // of ans                ans = Math.max(ans, i + 1)            }             // If freq2 and count2 is 1            // or freq1 and count1 is 1            if ((freq2 == 1 && count2 == 1) ||                (freq1 == 1 && count1 == 1)) {                 // Update the value of                // ans                ans = Math.max(ans, i + 1)            }        }    }     // Return ans    return ans }  // Driver Code let arr = [1, 1, 1, 2, 2, 2, 3,    3, 3, 4, 4, 4, 5]N = arr.length document.write(maxPrefixLen(arr, N)) // This code is contributed by gfgking</script>
13
 
Time Complexity: O(N)Auxiliary Space: O(N)
 
mohit kumar 29
gfgking
cpp-map
frequency-counting
prefix
Arrays
Arrays
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Window Sliding Technique
Building Heap from Array
Trapping Rain Water
Program to find sum of elements in a given array
Reversal algorithm for array rotation
Move all negative numbers to beginning and positive to end with constant extra space
Find duplicates in O(n) time and O(1) extra space | Set 1
Count pairs with given sum
Next Greater Element
Remove duplicates from sorted array