{x}
blog image

Sort Array by Increasing Frequency

Given an array of integers nums, sort the array in increasing order based on the frequency of the values. If multiple values have the same frequency, sort them in decreasing order.

Return the sorted array.

 

Example 1:

Input: nums = [1,1,2,2,2,3]
Output: [3,1,1,2,2,2]
Explanation: '3' has a frequency of 1, '1' has a frequency of 2, and '2' has a frequency of 3.

Example 2:

Input: nums = [2,3,1,3,2]
Output: [1,3,3,2,2]
Explanation: '2' and '3' both have a frequency of 2, so they are sorted in decreasing order.

Example 3:

Input: nums = [-1,1,-6,4,5,-6,1,4,1]
Output: [5,-1,4,4,-6,-6,1,1,1]

 

Constraints:

  • 1 <= nums.length <= 100
  • -100 <= nums[i] <= 100

Solution Explanation

This problem requires sorting an array based on the frequency of elements. If frequencies are equal, elements should be sorted in descending order. The optimal approach involves using a hash map (or dictionary) to count element frequencies and then sorting the array based on a custom comparison function that considers both frequency and value.

Approach

  1. Frequency Counting: First, we count the frequency of each element in the input array nums. This is efficiently done using a hash map (dictionary in Python, HashMap in Java/C++/Rust, Map in Javascript/Typescript). The keys are the array elements, and the values are their frequencies.

  2. Custom Sorting: We use a custom sorting function (or lambda/closure in some languages) as the key for the sorted() function (Python) or sort() method (other languages). This function compares two elements a and b based on their frequencies:

    • If the frequencies are different, it sorts based on increasing frequency (cnt[a] - cnt[b] or equivalent).
    • If the frequencies are the same, it sorts in decreasing order of the element values (b - a or equivalent).
  3. Return Sorted Array: The sorted array is returned as the solution.

Time and Space Complexity

  • Time Complexity: O(N log N), where N is the length of the input array. The dominant operation is the sorting step, which typically has O(N log N) time complexity for efficient comparison-based sorting algorithms. Frequency counting takes O(N) time.

  • Space Complexity: O(N) in the worst case, to store the frequency map. In the best case, if all elements are unique, the space complexity will be O(N). The space used for sorting depends on the implementation of the sorting algorithm used by the language, but many implementations use O(log N) extra space.

Code Explanation (Python)

from collections import Counter
 
class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        cnt = Counter(nums)  # Efficiently counts element frequencies
        return sorted(nums, key=lambda x: (cnt[x], -x)) #Sorts by frequency (ascending) then value (descending)
 

The Counter object from the collections module efficiently creates a frequency count dictionary. The lambda function defines the custom comparison key, which first compares the frequencies (cnt[x]) and then uses the negative of the element value (-x) to sort in descending order if the frequencies are equal.

Code Explanation (Java)

import java.util.*;
class Solution {
    public int[] frequencySort(int[] nums) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int num : nums) {
            countMap.put(num, countMap.getOrDefault(num, 0) + 1);
        }
 
        Arrays.sort(nums, (a, b) -> {
            int freqA = countMap.get(a);
            int freqB = countMap.get(b);
            if (freqA != freqB) {
                return freqA - freqB; // Sort by increasing frequency
            } else {
                return b - a; // Sort by decreasing value if frequencies are equal
            }
        });
 
        return nums;
    }
}

The Java code uses a HashMap for frequency counting and Arrays.sort() with a custom Comparator lambda expression to sort the array based on the frequency and value criteria.

The other language implementations follow a similar pattern: frequency counting using a hash map/dictionary followed by a sort operation using a custom comparison function (lambda, closure, or comparator) to handle the dual sorting criteria.