---
# System prepended metadata

title: 'Gao''s LeetCode 101: Sorting'

---

# Gao's LeetCode 101: Sorting

## 0. Post Details

- Reference: [Gao et al., LeetCode 101 - A Grinding Guide, 2001.](https://noworneverev.github.io/leetcode_101/category/4-%E5%8D%83%E5%A5%87%E7%99%BE%E6%80%AA%E7%9A%84%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95) 
- Post by: Jedd Yang
- Date: 2025-09-10
- Keywords: Sort

## 1. Problems

### <font color="#FFA500"> 215. Kth Largest Element in an Array </font>

> Given an integer array nums and an integer k, return the kth largest element in the array. Note that it is the kth largest element in the sorted order, not the kth distinct element. Can you solve it without sorting?

:::success
- Approach： `nth_element()` (one pass of Quickselect), [use STL.](https://leetcode.com/problems/kth-largest-element-in-an-array/solutions/60309/c-stl-partition-and-heapsort)
- Complexity: Time $O(n)$; Space $O(1)$.
:::

```cpp=
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        nth_element(nums.begin(), nums.begin() + k - 1,
                    nums.end(), greater<int>());
        // or 
        // partial_sort(nums.begin(), nums.begin() + k, 
        // nums.end(), greater<int>());
        // but Time = O(n log k), k is the heap size
        return nums[k - 1];
    }
};
```

:::warning
- Approach： Three-way Quickselect.
- Complexity: Time $O(n^2)$; Space $O(1)$.
:::

```cpp=
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int pivotIndex = rand() % nums.size();
        int pivot = nums[pivotIndex];
        
        vector<int> larger, equal, smaller;
        
        for(int num : nums){
            if (num > pivot){
                larger.push_back(num);
            }else if(num < pivot){
                smaller.push_back(num);
            }else{
                equal.push_back(num);
            }
        }
        
        if(k <= larger.size()){
            return findKthLargest(larger, k);
        }
        if(k > larger.size() + equal.size()){
            return findKthLargest(smaller, k - larger.size() - equal.size());
        }
        return pivot;
    }
};
```

:::danger
- Approach： Quicksort. The slowest for this problem.
- Complexity: Time $O(n^2)$; Space $O(1)$
:::

```cpp=
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        quickSort(nums, 0, nums.size() - 1);
        // after full ascending sort, k-th largest is at size - k
        return nums[nums.size() - k];
    }

private:
    void quickSort(vector<int>& a, int left, int right) {
        if (left >= right) return;

        int pivotIndex = left + rand() % (right - left + 1);
        int pivot = a[pivotIndex];

        int i = left, j = right;
        while (i <= j) {
            while (a[i] < pivot) i++;
            while (a[j] > pivot) j--;
            if (i <= j) {
                swap(a[i], a[j]);
                i++;
                j--;
            }
        }

        // Recurse into both halves
        if (left < j)  quickSort(a, left, j);
        if (i < right) quickSort(a, i, right);
    }
};
```

### <font color="#FFA500"> 347. Top K Frequent Elements </font>

> Given an integer array `nums` and an integer `k`, return the `k` most frequent elements. You may return the answer in any order.

:::warning
- Approach： Hash table without sort, hash from larger number to small.
- Complexity: Time $O(n)$; Space $O(n)$.
:::

```cpp=
class Solution {
   public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        
        // create a hash_table, number : frequency
        unordered_map<int, int> numFrequency;
        for (int num : nums) {
            ++numFrequency[num];
        }
        
        // create a hash_table, frequency : [number1, number2, ...]
        unordered_map<int, vector<int>> buckets;
        for (auto [num, freq] : numFrequency) {
            // bcs different num can appear in same frequency
            buckets[freq].push_back(num);
        }
        
        // create a return vector, keep adding numbers til k is met
        vector<int> top_k;
        for (int count = nums.size(); count >= 0; --count) {
            if (buckets.find(count) != buckets.end()) {
                for (int num : buckets[count]) {
                    top_k.push_back(num);
                    if (top_k.size() == k) return top_k;
                }
            }
        }
        // corner case, if nums.size() < k
        return top_k;
    }
};

```

### <font color="#FFA500"> 451. Sort Characters By Frequency </font>

> Given a string `s`, sort it in decreasing order based on the frequency of the characters. The frequency of a character is the number of times it appears in the string.
>
> Return the sorted string. If there are multiple answers, return any of them.

:::danger
- Approach：Priority queue. Use BST (`map`) and queue (`priority_queue`).
- Complexity: Time $O(n log n)$; Space $O(n)$.
:::

```cpp=
class Solution {
public:
    string frequencySort(string s) {
        priority_queue<pair<int, char>> pq;
        map<char, int> m;
        for (auto i:s){
            ++m[i];
        }
        for (auto i:s){
            pq.push({m[i], i});
        }
        string ans;
        
        while(!pq.empty()){
            ans.push_back(pq.top().second); // second value of the pair
            pq.pop();
        }

        return ans;
    }
};
```

:::warning
- Approach：Bucket sort.
- Complexity: Time $O(n log n)$; Space $O(n)$.
:::

```cpp=
class Solution {
public:
    string frequencySort(string s) {
        // 1. Count frequencies
        unordered_map<char, int> freq;
        for (char c : s){
            ++freq[c];
        }

        // 2. Buckets: index = frequency
        unordered_map<int, vector<char>> buckets;
        int maxFreq = 0; // to track the maximum frequency
        for (auto &[c, f] : freq) {
            buckets[f].push_back(c);
            if (f > maxFreq) maxFreq = f;
        }

        // 3. Build answer from high frequency to low
        string ans;
        for (int f = s.size(); f >= 0; --f){
            if (buckets.find(f) != buckets.end()) {
                for (char c : buckets[f]) {
                    ans.append(f, c);
                }
            }
        }

        return ans;
    }
};
```

:::success
- Approach：Multimap (BST).
- Complexity: Time $O(n log n)$; Space $O(n)$.
:::

```cpp=
class Solution {
public:
    string frequencySort(string s) {
        unordered_map<char,int> mp;
        multimap<int,char> r; // allows duplicate keys.
        string ans = "";

        for(auto a : s)
            mp[a]++;
        
        // the multimap will sort the key from small to large automatically
        for(auto a : mp)
            r.insert({a.second, a.first});
        
        // rbegin and rend, the reverse iterators
        for(auto it = r.rbegin(); it != r.rend(); ++it) 
            ans += string(it->first, it->second); // string(count, char)

        return ans;
    }
};
```

>[!Tip] Why multimap instead of unordered_multimap
> `multimap` is a BST ordered by key (frequency). Iterating in reverse gives highest frequency first automatically. No extra sorting needed. `unordered_multimap` is a hash table. Keys are unordered. If we used it, we would need an extra sort step to process the frequencies in descending order.

### <font color="#FFA500"> 75. Sort Colors </font>

> Given an array `nums` with `n` objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue. We will use the integers `0`, `1`, and `2` to represent the color red, white, and blue, respectively. You must solve this problem without using the library's sort function.

:::warning
- Approach：Bucket sort.
- Complexity: Time $O(n)$; Space $O(n)$.
:::

```cpp=
class Solution {
public:
    void sortColors(vector<int>& nums) {
        // bucket sort
        // use map bcs i want it in order
        map<int, vector<int>> loc;
        for (int i = 0; i < nums.size(); ++i) {
            loc[nums[i]].push_back(i);
        }

        int writePos = 0;
        for (auto &kv : loc) {
            // debug
            // -----
            // std::cout << "key: " << kv.first << " -> [";
            // for (size_t i = 0; i < kv.second.size() ; ++i){
            //     std::cout << kv.second[i];
            //     if (i + 1 < kv.second.size()) std::cout << ", ";
            // }
            // std::cout << "]\n";
            // -----

            int key = kv.first;
            auto& vec = kv.second;
            for (size_t s = 0; s < vec.size(); ++s){
                nums[writePos++] = key;
            }
        }
    }
};
```

>[!Tip] Is storing index necessary?
> The problem requires us to print out `0, 1, 2` in ascending order, so no need to store the indices!

:::success
- Approach：Countinf sort.
- Complexity: Time $O(n)$; Space $O(1)$.
:::

```cpp=
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int count[3] = {0, 0, 0};

        for (int n : nums){
            ++count[n];
        }

        int writePos = 0;
        for (int color = 0; color < 3; ++color) {
            for (int k = 0; k < count[color]; ++k){
                nums[writePos++] = color;
            }
        }
    }
};
```
