|
| 1 | +import java.util.*; |
| 2 | +import java.util.stream.Collectors; |
| 3 | + |
| 4 | +class Solution { |
| 5 | + public int[] topKFrequent(int[] nums, int k) { |
| 6 | + /** |
| 7 | + k번째로 많이 등장한 숫자를 구하는 문제. |
| 8 | + 구해야 하는 것. |
| 9 | + 1. 등장횟수의 순위 |
| 10 | + 2. k번째 순위에 해당하는 수의 값 |
| 11 | +
|
| 12 | + 1. 등장 횟수를 구하는 방법: 전체를 순회해 숫자별 등장 횟수를 저장 -> O(N) |
| 13 | + 2. 등장 횟수의 순위를 구하는 방법: 등장 횟수에 대해 sort |
| 14 | + -> O(MlogM) where N = M(M+1) / 2 |
| 15 | + -> logN = logM + log(M+1) + C |
| 16 | + -> M = N^(1/2) |
| 17 | + -> O(MlogM) = O(N^1/2logN) (??? 여기가 맞는지 모르겠네요..) |
| 18 | + 3. 역 인덱스를 구해 매핑되는 수를 구함 -> O(N) |
| 19 | +
|
| 20 | + 전체: O(N) |
| 21 | + */ |
| 22 | + Map<Integer, Integer> numToCount = new HashMap<>(); |
| 23 | + for (int num : nums) { // O(N) |
| 24 | + numToCount.put(num, numToCount.getOrDefault(num, 0) + 1); |
| 25 | + } |
| 26 | + |
| 27 | + Map<Integer, List<Integer>> countToNum = new HashMap<>(); |
| 28 | + for (Map.Entry<Integer, Integer> entry: numToCount.entrySet()) { |
| 29 | + List<Integer> numList = countToNum.getOrDefault(entry.getValue(), new ArrayList<>()); |
| 30 | + numList.add(entry.getKey()); |
| 31 | + countToNum.put(entry.getValue(), numList); |
| 32 | + } // O(logN): because sum of all counts is equal to N |
| 33 | + |
| 34 | + List<Integer> countRank = countToNum.keySet().stream().sorted(Collections.reverseOrder()).collect(Collectors.toList()); |
| 35 | + // O(MlogM) where N = M(M+1) / 2 |
| 36 | + |
| 37 | + int[] ret = new int[k]; |
| 38 | + int idx = 0; |
| 39 | + int rank = 0; |
| 40 | + while (idx < k) { // O(k) <= O(N) |
| 41 | + for (int num : countToNum.get(countRank.get(rank++))) { |
| 42 | + ret[idx++] = num; |
| 43 | + } |
| 44 | + } |
| 45 | + return ret; |
| 46 | + } |
| 47 | +} |
0 commit comments