[Medium] 406. Queue Reconstruction by Height
[Medium] 406. Queue Reconstruction by Height
You are given an array of people, people, which are the attributes of some people in a queue (not necessarily in order). Each people[i] = [hi, ki] represents the ith person of height hi with exactly ki other people who have a height greater than or equal to hi in front of them.
Write an algorithm to reconstruct the queue.
Examples
Example 1:
Input: people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
Output: [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
Explanation:
Person 0 has height 5 with no one taller or equal in front of them.
Person 1 has height 7 with no one taller or equal in front of them.
Person 2 has height 5 with two people taller or equal in front of them.
Person 3 has height 6 with one person taller or equal in front of them.
Person 4 has height 4 with four people taller or equal in front of them.
Person 5 has height 7 with one person taller or equal in front of them.
Example 2:
Input: people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
Output: [[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]
Explanation:
Person 0 has height 4 with no one taller or equal in front of them.
Person 1 has height 5 with no one taller or equal in front of them.
Person 2 has height 2 with two people taller or equal in front of them.
Person 3 has height 3 with two people taller or equal in front of them.
Person 4 has height 1 with four people taller or equal in front of them.
Person 5 has height 6 with no one taller or equal in front of them.
Constraints
1 <= people.length <= 20000 <= hi <= 10^60 <= ki < people.length- It is guaranteed that the queue can be reconstructed.
Solution: Greedy Sorting with List Insertion
Time Complexity: O(n²) where n is the number of people
Space Complexity: O(n) for the result list
Sort people by height (descending) and k-value (ascending), then insert each person at the k-th position using a list for efficient insertion.
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
/*
1. Sort by height (descending), then by k-value (ascending)
2. Insert each person at the k-th position
3. Use list for efficient insertion at arbitrary positions
*/
sort(people.begin(), people.end(), [](const vector<int> & a, const vector<int>& b) {
if(a[0] == b[0]) return a[1] < b[1]; // Same height: sort by k-value
return a[0] > b[0]; // Different height: sort by height
});
list<vector<int>> rtn;
for(auto& person: people) {
auto it = rtn.begin();
advance(it, person[1]); // Move iterator to k-th position
rtn.insert(it, person);
}
return vector<vector<int>>(rtn.begin(), rtn.end());
}
};
How the Algorithm Works
Key Insight: Sort people by height (descending) and k-value (ascending), then insert each person at the k-th position.
Steps:
- Sort people by height (descending) and k-value (ascending)
- Use list for efficient insertion at arbitrary positions
- For each person:
- Move iterator to k-th position
- Insert person at that position
- Convert list to vector and return
Step-by-Step Example
Example: people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
Step 1: Sort by height (descending) and k-value (ascending)
Original: [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
Sorted: [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]
Step 2: Insert each person at k-th position
| Person | Height | K | List State | Insertion Position |
|---|---|---|---|---|
| [7,0] | 7 | 0 | [] | Position 0 → [[7,0]] |
| [7,1] | 7 | 1 | [[7,0]] | Position 1 → [[7,0],[7,1]] |
| [6,1] | 6 | 1 | [[7,0],[7,1]] | Position 1 → [[7,0],[6,1],[7,1]] |
| [5,0] | 5 | 0 | [[7,0],[6,1],[7,1]] | Position 0 → [[5,0],[7,0],[6,1],[7,1]] |
| [5,2] | 5 | 2 | [[5,0],[7,0],[6,1],[7,1]] | Position 2 → [[5,0],[7,0],[5,2],[6,1],[7,1]] |
| [4,4] | 4 | 4 | [[5,0],[7,0],[5,2],[6,1],[7,1]] | Position 4 → [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] |
Final result: [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
Algorithm Breakdown
Sorting Logic:
sort(people.begin(), people.end(), [](const vector<int> & a, const vector<int>& b) {
if(a[0] == b[0]) return a[1] < b[1]; // Same height: sort by k-value
return a[0] > b[0]; // Different height: sort by height
});
Process:
- Primary sort: By height (descending)
- Secondary sort: By k-value (ascending) for same height
- Result: Tallest people first, then by k-value
Insertion Logic:
for(auto& person: people) {
auto it = rtn.begin();
advance(it, person[1]); // Move iterator to k-th position
rtn.insert(it, person);
}
Process:
- Start iterator at beginning of list
- Advance iterator to k-th position
- Insert person at that position
- Repeat for all people
Complexity Analysis
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Sorting | O(n log n) | O(1) |
| Insertion | O(n²) | O(n) |
| Total | O(n²) | O(n) |
Where n is the number of people.
Edge Cases
- Single person:
people = [[5,0]]→[[5,0]] - All same height:
people = [[5,0],[5,1],[5,2]]→[[5,0],[5,1],[5,2]] - All k=0:
people = [[7,0],[6,0],[5,0]]→[[5,0],[6,0],[7,0]] - Maximum k:
people = [[1,2]]→[[1,2]]
Key Insights
Greedy Strategy:
- Tallest first: Process tallest people first
- K-value ordering: For same height, process by k-value
- Insertion order: Insert at k-th position
- Optimal result: Always produces correct reconstruction
Why This Works:
- Tallest people: Can be placed anywhere without affecting others
- K-value constraint: Each person needs exactly k taller people in front
- Insertion order: Maintains the constraint for all people
- List efficiency: O(1) insertion at arbitrary positions
Detailed Example Walkthrough
Example: people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
Step 1: Sort by height (descending) and k-value (ascending)
Original: [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
Sorted: [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
Step 2: Insert each person at k-th position
| Person | Height | K | List State | Insertion Position |
|---|---|---|---|---|
| [6,0] | 6 | 0 | [] | Position 0 → [[6,0]] |
| [5,0] | 5 | 0 | [[6,0]] | Position 0 → [[5,0],[6,0]] |
| [4,0] | 4 | 0 | [[5,0],[6,0]] | Position 0 → [[4,0],[5,0],[6,0]] |
| [3,2] | 3 | 2 | [[4,0],[5,0],[6,0]] | Position 2 → [[4,0],[5,0],[3,2],[6,0]] |
| [2,2] | 2 | 2 | [[4,0],[5,0],[3,2],[6,0]] | Position 2 → [[4,0],[5,0],[2,2],[3,2],[6,0]] |
| [1,4] | 1 | 4 | [[4,0],[5,0],[2,2],[3,2],[6,0]] | Position 4 → [[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]] |
Final result: [[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]
Alternative Approaches
Approach 1: Vector with Insertion
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), [](const vector<int>& a, const vector<int>& b) {
if(a[0] == b[0]) return a[1] < b[1];
return a[0] > b[0];
});
vector<vector<int>> result;
for(auto& person: people) {
result.insert(result.begin() + person[1], person);
}
return result;
}
};
Time Complexity: O(n²)
Space Complexity: O(n)
Approach 2: Priority Queue
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
priority_queue<pair<int, int>> pq;
for(auto& person: people) {
pq.push({person[0], person[1]});
}
vector<vector<int>> result;
while(!pq.empty()) {
auto [h, k] = pq.top();
pq.pop();
result.insert(result.begin() + k, {h, k});
}
return result;
}
};
Time Complexity: O(n²)
Space Complexity: O(n)
Common Mistakes
- Wrong sorting order: Not sorting by height descending first
- Incorrect k-value handling: Not considering k-value for same height
- Wrong insertion position: Inserting at wrong index
- Data structure choice: Using vector instead of list for insertion
Related Problems
Why This Solution Works
Greedy Strategy:
- Tallest first: Process tallest people first
- K-value ordering: For same height, process by k-value
- Insertion order: Insert at k-th position
- Optimal result: Always produces correct reconstruction
List Efficiency:
- O(1) insertion: Insert at arbitrary positions
- Iterator advancement: Efficient position finding
- Memory efficient: No extra space for insertion
- Optimal performance: Better than vector insertion
Key Algorithm Properties:
- Correctness: Always produces valid reconstruction
- Optimality: Produces correct queue order
- Efficiency: O(n²) time complexity
- Simplicity: Easy to understand and implement