Skip to content
Related Articles

Related Articles

Improve Article

Find the maximum length of the prefix | Set-2

  • Last Updated : 15 Jul, 2021
Geek Week

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 <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum
// length of the required prefix
int 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 Code
int 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




// Java program for the above approach
import 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




# Python3 program for the above approach
 
# Function to find the maximum
# length of the required prefix
def 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 Code
if __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




<script>
// Javascript program for the above approach
 
// Function to find the maximum
// length of the required prefix
function 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>
Output: 
13

 

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

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :