문제
input : 정수 배열 nums, 정수 k
output : 배열에서 중복 된 개수가 많은 순으로 k개의 값을 반환한다.(정확한 순서는 상관 없다.)
시간 복잡도
이 문제에서 n은 배열의 길이로 최대 $100,000$를 가진다.
각 복잡도를 계산하면 이러하다.
- $n^2 = 10'000'000'000 \ \ \text{불가능}$
- $n \log{n} = 100'000 \times 20 \approx 2'000'000 \ \ \text{가능}$
때문에, $n \log{n}$ 이하부터 고려하면 좋다.
하지만 문제 풀 때 복잡도 계산을 잘못해서 $n \log{n}$제외한 상태에서 풀이를 진행했다..ㅎ
해결 계획
처음 생각한 방법은 등장 횟수를 저장하는 배열을 만드는 방식이였다.
// table[i] : nums의 값이 i인 원소의 개수
// 음수도 존재하기 때문에 1000을 더하여 사용, -1000 = table[0]
int table[2020] = { 0 };
for (const int data : nums)
{
table[data + 1000]++;
}
이런 방식으로 구성하려고 했고 저장한 테이블을 순회하여 k만큼의 최대값을 저장하면서 반환하는 방식이였다.
이렇게 되면 복잡도가 $2n$이 되기 때문에 빠르고 가능할거라고 생각했다.
근데 최대 값을 저장하는 로직 부분에서, 아래와 같이 최대 값을 하나만 기억하려고 했던걸 생각해서 그런지 k개의 값들을 기억하고 관리하기에는 좀 까다로웠다.
// 너무 단순하게 생각했었던 로직
int maxNum = 0;
for (int i =0 ; i < tableSize; ++i)
{
maxNum = max(table[i], maxNum);
}
그래서 생각한게, 전체 정렬을 하지 않아도 K개만 잘 꺼내기만 하면 되지 않나? 라는 생각이 들어 우선순위 큐를 고려했다.
복잡도 또한 push와 pop이 log n 이니까 가능하다 생각했다.
큐에 저장해야하는 건 값과 등장 횟수 두 가지라 자연스럽게 pair를 생각했다.
기존 배열을 이용해 큐에 저장하려고 했는데 뭔가 번거로웠다.
// 뭔가 번거로움
for (int i = 0; i < table.size(); ++i)
{
if (table[i] == 0) continue;
queue.push({table[i], i);
}
그래서 대안을 찾다가 해시를 생각했는데, 희소 원소도 제거되고 해시 테이블을 순회 할 때 pair를 반환하니까 한번에 주면 되겠다 싶어서 해시로 변경하여 진행했다.
구현
vector<int> topKFrequent(vector<int>& nums, int k) {
// @first : nums의 값
// @second : first가 nums에 포함된 개수
unordered_map<int,int> table;
for (const int data : nums)
{
table[data]++;
}
// push queue
priority_queue<pair<int,int>> q;
for (const auto& data : table)
{
q.push({data.second, data.first});
}
// pop queue
vector<int> result;
result.reserve(k);
while (k--)
{
result.push_back(q.top().second);
q.pop();
}
return result;
}
되돌아보기
우선순위 큐를 너무 오랜만에 써서 pari형은 직접 정렬 함수를 설정해야 하는줄 알고 뻘짓을 했었다.
first를 먼저 비교, 값이 같다면 second를 비교하는 방식으로 정렬을 자동으로 수행해준다.
그리고 덤으로 알게 된건, C++은 기본이 내림차순이고 java는 기본이 오름차순인 것처럼 기본 정렬 순서가 다른 이유는,
각 우선순위에 대한 철학이 달라서 생기는 차이라고 한다! 사실인지는 모르지만.. ㅎ
그리고 우선 순위 큐라는 힌트를 나중되서 생각이 들었는데,
굳이 전체 정렬하지 않아도 된다 라는 워드에서 이미 우선순위 큐에 대한 힌트를 준게 아닌가 싶다..!
'코딩 테스트 > 알고리즘 풀이' 카테고리의 다른 글
| [Leet code - 973] K Closest Points to Origin ✅ (0) | 2026.02.27 |
|---|---|
| [Leet code - 739] Daily Temperatures ✅ (0) | 2026.02.26 |
| [Leet code - 20] Valid Parentheses ✅ (0) | 2026.02.26 |
| [Leet code - 75] Sort Colors ✅ (0) | 2026.02.13 |
| [Leet code - 49] Group Anagrams ✅ (0) | 2026.02.10 |
| [Leet code - 217] Contains Duplicate ✅ (0) | 2026.02.10 |
| [Leet code - 1] Two Sum ✅ (0) | 2026.02.09 |
| [백준 - 1018] 체스판 다시 칠하기 ✅ (0) | 2026.02.02 |
