Frequency of the Most Frequent Element

Updated on 30 May, 2025
Frequency of the Most Frequent Element header image

Problem Statement

In this problem, you are provided with an integer array nums and an integer k. The frequency of an element within the array is defined as how often that element appears in the array. Your goal is to determine the maximum frequency an element can reach if you are allowed to perform up to k operations on the array, where each operation consists of selecting an array index and incrementing the value at that index by 1. The task is to compute the highest possible frequency an element can achieve after performing these operations, given the constraints of the operation count and the array itself.

Examples

Example 1

Input:

nums = [1,2,4], k = 5

Output: 3** Explanation:**

Increment the first element three times and the second element two times to make nums = [4,4,4].
4 has a frequency of 3.

Example 2

Input:

nums = [1,4,8,13], k = 5

Output:

2

Explanation:

There are multiple optimal solutions:
- Increment the first element three times to make nums = [4,4,8,13]. 4 has a frequency of 2.
- Increment the second element four times to make nums = [1,8,8,13]. 8 has a frequency of 2.
- Increment the third element five times to make nums = [1,4,13,13]. 13 has a frequency of 2.

Example 3

Input:

nums = [3,9,6], k = 2

Output:

1

Constraints

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105
  • 1 <= k <= 105

Approach and Intuition

This problem can be approached by strategically increasing the values in the array to maximize the frequency of any particular number. Here's an intuitive step-by-step plan to solve the problem:

  1. Sort the array to help in efficiently finding and incrementing the closest numbers, aiming to make them equal and thus increasing their frequency.
  2. Use two pointers or a sliding window approach:
    • The left pointer (start) will track the start of a window.
    • The right pointer (end) will track the end of a window.
  3. As you slide the end pointer from the start of the array to the end:
    • Calculate the total increment needed for all elements from start to end to match the element at end.
    • If the total increments required is less than or equal to k, then it's possible to make all elements between start and end the same as the element at end.
    • Keep track of the maximum number of elements you can make identical within the limit of k operations.
  4. If at any point, the increments needed to make all values from start to end identical surpass k, move the start pointer to the right to potentially decrease the required increments.
  5. Continue this process until you've traversed the entire array.

This method leverages the efficiency of the two-pointer technique to explore ranges within the array and the sort operation helps in minimizing the number of increments needed to equalize parts of the array, potentially maximizing the frequency of an element.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int findMaxFrequency(int i, int allowedOps, vector<int>& numList, vector<long>& cumulative) {
        int soughtVal = numList[i];
        int low = 0;
        int high = i;
        int bestPosition = i;
        
        while (low <= high) {
            int middle = (low + high) / 2;
            long elementsCount = i - middle + 1;
            long neededSum = elementsCount * soughtVal;
            long currentSum = cumulative[i] - cumulative[middle] + numList[middle];
            int opsNeeded = neededSum - currentSum;
            
            if (opsNeeded > allowedOps) {
                low = middle + 1;
            } else {
                bestPosition = middle;
                high = middle - 1;
            }
        }
        
        return i - bestPosition + 1;
    }
    
    int maximumFrequency(vector<int>& numList, int allowedOps) {
        sort(numList.begin(), numList.end());
        vector<long> cumulative;
        cumulative.push_back(numList[0]);
        
        for (int i = 1; i < numList.size(); i++) {
            cumulative.push_back(numList[i] + cumulative.back());
        }
        
        int maxFreq = 0;
        for (int i = 0; i < numList.size(); i++) {
            maxFreq = max(maxFreq, findMaxFrequency(i, allowedOps, numList, cumulative));
        }
        
        return maxFreq;
    }
};

The code snippet provided in C++ offers a solution to determine the maximum frequency of an element in a list after performing up to a specified number of increment operations to make elements equal. This solution utilizes a combination of binary search and prefix sums for efficiency.

Here's a breakdown of how the code operates:

  • The findMaxFrequency function calculates the maximum number of times an element numList[i] can appear by adjusting elements to the left of i (inclusive) within the allowed number of operations. It uses binary search to efficiently find how many previous elements can be turned into numList[i]. Given the sorted nature of numList, the search determines the position bestPosition where the sum of required operations to make all elements from bestPosition to i equal to numList[i] is within the allowed limit.

  • The main function maximumFrequency first sorts the input list numList. It then creates a cumulative sum array cumulative to help compute the sum of any sub-array in constant time, a common technique to speed up such computations.

  • It iterates over each element in the sorted list, using findMaxFrequency to compute and keep track of the highest frequency possible by adjusting elements up to that index.

Key traits of this solution include:

  • Efficiency through sorting and the use of prefix sums, which allows quick access to range sums.
  • Binary search within the findMaxFrequency function significantly speeds up the process of finding the maximum range of elements that can be adjusted to match a given number.
  • The use of two key metrics, the operations needed opsNeeded and current frequency elementsCount, to determine the potential of each element in achieving a high frequency given the operation constraints.

By understanding these mechanisms, you effectively grasp how the code maximizes the frequency of any given element subject to certain modifications, a valuable technique for challenges involving optimized modifications within constraints.

java
class Solution {
    public int findMaxFreq(int idx, int capacity, int[] values, long[] accumulated) {
        int focalPoint = values[idx];
        int minIdx = 0;
        int maxIdx = idx;
        int optimum = idx;
        
        while (minIdx <= maxIdx) {
            int middle = (minIdx + maxIdx) / 2;
            long count = idx - middle + 1;
            long desiredSum = count * focalPoint;
            long sumUntilMid = accumulated[idx] - accumulated[middle] + values[middle];
            long opsNeeded = desiredSum - sumUntilMid;
            
            if (opsNeeded > capacity) {
                minIdx = middle + 1;
            } else {
                optimum = middle;
                maxIdx = middle - 1;
            }
        }
        
        return idx - optimum + 1;
    }
    
    public int maxFrequency(int[] array, int k) {
        Arrays.sort(array);
        long[] cumSum = new long[array.length];
        cumSum[0] = array[0];
        
        for (int i = 1; i < array.length; i++) {
            cumSum[i] = array[i] + cumSum[i - 1];
        }
        
        int res = 1;
        for (int i = 0; i < array.length; i++) {
            res = Math.max(res, findMaxFreq(i, k, array, cumSum));
        }
        
        return res;
    }
}

The Java program provided focuses on computing the maximum frequency of any element in an integer array after making at most k increment operations. Here's an outline describing how the solution operates:

  • The maxFrequency function initiates by sorting the array. It then computes a prefix sum of this array to facilitate range sum queries which are used later to determine the number of operations needed.
  • A helper function findMaxFreq is employed to determine the maximum frequency for each element in the sorted array. This function efficiently identifies the longest subarray ending at a certain index where all elements can be increased to match the current element using no more than k increases.
    • It utilizes binary search to find the optimal starting index of the subarray. If transforming the subarray's elements to the current element's value requires operations exceeding k, the search space is adjusted.
    • The core calculation involves the difference between the required sum (if all elements are the target value) and the actual sum of the current subarray.

The final result is determined by iterating over each element of the array and applying the findMaxFreq function, tracking the maximum value returned.

Through this solution:

  • Time complexity is driven by the sort operation O(n log n) and the binary search operations for each element, leading to an overall efficient approach.
  • Space complexity is predominantly O(n) due to the additional storage for the cumulative sum array.

This approach is optimal for situations where an array needs to be manipulated minimally to maximize the frequency of any one element by allowed increments, offering a balance between efficiency and simplicity.

python
class Solution:
    def maximumFrequency(self, values: List[int], max_ops: int) -> int:
        def valid(mid_idx):
            goal = values[mid_idx]
            low = 0
            high = mid_idx
            optimal = mid_idx
            
            while low <= high:
                middle = (low + high) // 2
                elements_count = mid_idx - middle + 1
                desired_sum = elements_count * goal
                actual_sum = pre_sum[mid_idx] - pre_sum[middle] + values[middle]
                needed_ops = desired_sum - actual_sum

                if needed_ops > max_ops:
                    low = middle + 1
                else:
                    optimal = middle
                    high = middle - 1
            
            return mid_idx - optimal + 1
        
        values.sort()
        pre_sum = [values[0]]
        
        for idx in range(1, len(values)):
            pre_sum.append(values[idx] + pre_sum[-1])
        
        maximumFrequency = 0
        for idx in range(len(values)):
            maximumFrequency = max(maximumFrequency, valid(idx))
            
        return maximumFrequency

This solution elaborates on a Python-based method used to compute the highest frequency that a list of integers can reach after modifying elements, using a limited number of permissible operations. The process involves increasing any number in the array to any other higher or equal number within the same array.

Here’s a succinct breakdown of how the provided code tackles the problem:

  • Initial Preparation:

    • First, it sorts the list values to ease the comparisons and calculations that follow.
    • It computes the prefix sum pre_sum of the array, an array where each position i defines the sum of the array values from the start up to i.
  • Core Function – valid(mid_idx):

    • This nested function verifies how many elements can be elevated to the value at mid_idx without exceeding the allowed operations.
    • It employs binary search to optimize calculations through:
      • Defining a goal of accumulating all values till mid_idx to the value at mid_idx.
      • Using two-pointers, low and high, to squeeze towards the optimal subset starting point.
      • Estimating operations needed to achieve the goal, adjusting pointers based on whether these operations exceed max_ops.
  • Main Execution Loop Over Values:

    • Iterates over each index in values and, for each index, calculates the maximum achievable frequency using valid(), comparing and storing the higher frequencies as it progresses.
  • Return Maximum Frequency:

    • At the end, the function outputs the maximum frequency found.

This algorithm is structured efficiently with the binary search inside the valid() function reducing potential time complexity, and the use of prefix sums assists in fast computation of the sum of subsets of the list. This approach ensures that the function can handle large inputs within reasonable time limits by focusing computational resources intelligently.

Comments

No comments yet.