-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path0347-Top_K_Frequent_Elements.cpp
More file actions
141 lines (128 loc) · 3.23 KB
/
0347-Top_K_Frequent_Elements.cpp
File metadata and controls
141 lines (128 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*******************************************************************************
* 0347-Top_K_Frequent_Elements.cpp
* Billy.Ljm
* 22 May 2023
*
* =======
* Problem
* =======
* https://leetcode.com/problems/top-k-frequent-elements/
*
* Given an integer array nums and an integer k, return the k most frequent
* elements. You may return the answer in any order.
*
* ===========
* My Approach
* ===========
* We'll count the frequency of each integer in a map of {integer : occurrences},
* and use the quickselect algorithm to find the k smallest ones.
*
* This has a time complexity of O(n) and space complexity of O(n), where n is
* the number of integers.
******************************************************************************/
#include <iostream>
#include <vector>
#include <map>
/**
* Solution
*/
class Solution {
private:
/**
* One iteration of quickselect. Select last element as pivot value.
*
* @param arr vector of {key, value} to sort by value
* @param start starting index to sort from
* @param end ending index to sort from
*
* @return sorted index of pivot value
*/
int quickSelect(std::vector<std::pair<int, int>>& arr, int start, int end) {
int idx = start; // index to insert into
for (int i = start; i < end; i++) {
// note strictly greater than, otherwise quickselect can infinitely
// loop when there are multiple kth frequent values. (e.g. {a, b}
// with equal frequency will put pivot into 1 and never 0)
if (arr[i].second > arr[end].second) {
std::swap(arr[idx], arr[i]);
idx++;
}
}
std::swap(arr[idx], arr[end]);
return idx;
}
public:
/**
* Finds the k most frequent integers in a vector
*
* @param nums vector to search in
* @param k number of most frequent integers to return
*
* @return vector of the k most frequent integers
*/
std::vector<int> topKFrequent(std::vector<int>& nums, int k) {
// count number of occurences
std::map<int, int> freq;
for (int num : nums) {
if (freq.find(num) == freq.end()) {
freq[num] = 1;
}
else {
freq[num]++;
}
}
// convert to vector for sorting
std::vector<std::pair<int, int>> vec;
for (auto it : freq) {
vec.push_back({ it.first, it.second });
}
// quickselect algorithm
if (vec.size() > k) {
int start = 0;
int end = vec.size() - 1;
int pivot = quickSelect(vec, start, end);
while (pivot != k) {
if (pivot > k) end = pivot - 1;
else start = pivot + 1;
pivot = quickSelect(vec, start, end);
}
}
// convert to ouput
std::vector<int> out;
for (int i = 0; i < k; i++) {
out.push_back(vec[i].first);
}
return out;
}
};
/**
* << operator for vectors
*/
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
os << "[";
for (int i = 0; i < v.size(); i++) {
os << v[i] << ",";
}
os << "\b]";
return os;
}
/**
* Test cases
*/
int main(void) {
Solution sol;
std::vector<int> nums;
int k;
// test case 1
nums = { 1, 1, 1, 2, 2, 3 };
k = 2;
std::cout << "topKFrequent(" << nums << "," << k << ") = " <<
sol.topKFrequent(nums, k) << std::endl;
// test case 2
nums = { 1 };
k = 1;
std::cout << "topKFrequent(" << nums << "," << k << ") = " <<
sol.topKFrequent(nums, k) << std::endl;
return 0;
}