Find the maximum length of the prefix | Set-2

• Last Updated : 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:

1. The prefix over the range [0, 0]. Removing the only element in the prefix will become empty.
2. 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.
3. 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.
4. 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.
5. 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.

1. Frequencies of all the elements of the prefix are equal to 1.
2. All the elements in the prefix window are the same.
3. 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.
4. 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).
• Finally, after completing the above steps print the value of ans.

Below is the implementation of the above approach:

C++

 // C++ program for the above approach#include 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 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 == 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);     cout << maxPrefixLen(arr, N);}

Java

 // 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 a = new HashMap();        HashMap b = new HashMap();         // 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().hashCode();                int q = b.keySet().toArray().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

 # 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 == 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())            q = list(b.keys())             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

Javascript


Output:
13

Time Complexity: O(N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up