1
2
3
4
5
from collections import Counter
from typing import List
import heapq, random
import numpy as np
from itertools import chai
692.Top K Frequent Words
Hashmap + Sorting
Given $n$ words,
- Build Hashmap: $O(n)$
- Sorting: $O(nlogn)$
Therefore, it takes $O(nlogn)$.
1
2
3
4
5
6
class Solution1:
def topKFrequent(self, words: List[str], k: int) -> List[str]:
ct = Counter(words)
return sorted(ct.keys(), key=lambda x: (-ct[x], x))[:k]
sol1 = Solution1()
1
2
3
words = ["i", "love", "leetcode", "i", "love", "coding"]
k = 3
print(sol.topKFrequent(words, k))
1
2
['i', 'love', 'coding']
Hashmap + Heap
- Build Hashmap takes $O(n)$
- Build Heap by counts: $O(n)$
- pop K words from the Heap: $O(klogn)$, where $k \le n$
Therefore, $O(n + klogn)$
1
2
3
4
5
6
7
8
class Solution2:
def topKFrequent(self, words: List[str], k: int) -> List[str]:
ct = Counter(words)
heap = [(-v, k) for k, v in ct.items()]
heapq.heapify(heap)
return [heapq.heappop(heap)[1] for _ in range(k)]
sol2 = Solution2()
1
2
3
words = ["i", "love", "leetcode", "i", "love", "coding"]
k = 3
print(sol.topKFrequent(words, k))
1
2
['i', 'love', 'coding']
451. Sort Characters By Frequency
1
2
3
4
5
6
7
8
9
10
class Solution:
def frequencySort(self, s: str) -> str:
cnt = Counter(s)
reorder = sorted(cnt.keys(), key=lambda x: -cnt[x])
ans = ''
for c in reorder:
ans += c * cnt[c]
return ans
sol = Solution()
1
2
s = "tree"
print(sol.frequencySort(s))
1
2
eetr
1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def frequencySort(self, s: str) -> str:
cnt = Counter(s)
heap = [(-v, k) for k, v in cnt.items()]
heapq.heapify(heap)
ans = ''
while heap:
c = heapq.heappop(heap)[1]
ans += c * cnt[c]
return ans
sol = Solution()
1
2
s = "tree"
print(sol.frequencySort(s))
1
2
eert
347. Top K Frequent Elements
The algorithm which use heap datas tructure takes $O(n + klogn)$
1
2
3
4
5
6
7
8
9
10
11
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
cnt = Counter(nums)
heap = [(-v, k) for k, v in cnt.items()]
heapq.heapify(heap)
return [heapq.heappop(heap)[1] for _ in range(k)]
sol = Solution()
nums = [1,1,1,2,2,3]
k = 2
print(sol.topKFrequent(nums, k))
1
2
[1, 2]
378. Kth Smallest Element in a Sorted Matrix
Given $n \times n$ matrix
, where the each rows and columns of the matrix is sorted in ascending order.
condition: $1 \le k \le n^2$
Unpack and Sorting
Ignored sorted conditions.
- unpack: $O(n^2)$
- sorting: $O(n^2logn^2)$
Therefore, $O(n^2logn^2)$
1
2
3
4
5
class Solution1:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
unpacked = list(chain.from_iterable(matrix))
return sorted(unpacked)[k - 1]
sol1 = Solution1()
1
2
3
4
5
6
matrix = \
[[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]]
k = 8
print(sol1.kthSmallest(matrix, k))
1
2
13
Unpack and Selection
- unpack: $O(n^2)$
- selection(average time): $O(n^2)$
Therefore, $O(n^2)$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution2:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
a = list(chain.from_iterable(matrix))
def select(p, r, k):
if p == r: return a[p]
i = random.randint(p, r)
a[i], a[r] = a[r], a[i]
i = p - 1
for j in range(p, r):
if a[j] < a[r]:
i += 1
a[i], a[j] = a[j], a[i]
a[i + 1], a[r] = a[r], a[i + 1]
q = i + 1
if q - p + 1 >= k:
return select(p, q, k)
else:
return select(q + 1, r, k - (q - p + 1))
return select(0, len(a) - 1, k)
sol2 = Solution2()
1
print(sol2.kthSmallest(matrix, k))
1
2
13
Use Heap, indexing of each node
- build heap: $O(n^2)$
- pop k elements: $O(klogn)$
Therefore, $O(klogn)$, but worst case $O(n^2logn)$
For helping understanding of this algorithm, I cited an article’s paragraph and exmaple as follows.
Since the matrix is sorted, we do not need to put all the elements in heap at one time.
We can simply pop and put for k times.
By observation, if we look at the matrix diagonally,
we can tell that if we do not pop matrix[i][j],
we do not need to put on matrix[i][j + 1] and matrix[i + 1][j] since they are bigger.
e.g., given the matrix below:
1 2 3 1 2 4 3 5 7 6 8 9We put 1 first, then pop 1 and put 2 and 3, then pop 2 and put 4 and 5, then pop 3 and put 6…
I cited from this article
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution3:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
heap = [(row[0], row, 1) for row in matrix]
heapq.heapify(heap)
# Since we want to find kth, we pop the first k elements
for _ in range(k - 1):
_, r, i = heap[0]
if i < len(r):
heapq.heapreplace(heap, (r[i], r, i + 1))
else:
heapq.heappop(heap)
return heap[0][0]
sol3 = Solution3()
1
print(sol3.kthSmallest(matrix, k))
1
2
13
Leave a comment