leetcode * 347. 앞의 K 개 고주파 요소 (쌓 기 정렬)

[제목] * 347. 앞의 K 개 고주파 원소
검 지 Offer 40. 최소 k 개 수 * 215. 배열 의 K 번 째 최대 원소 * 347. 앞의 K 개 고주파 원소
빈 정수 그룹 을 지정 하고 주파수 가 나 오기 전에 k 가 높 은 요 소 를 되 돌려 줍 니 다.
예시 1:
  : nums = [1,1,1,2,2,3], k = 2
  : [1,2]

예시 2:
  : nums = [1], k = 1
  : [1]

알림:
당신 은 주어진 k 가 항상 합 리 적 이 고 1 ≤ k ≤ 배열 에서 서로 다른 요소 의 개 수 를 가정 할 수 있 습 니 다.알고리즘 의 시간 복잡 도 는 O (n log n) 보다 높 아야 합 니 다. n 은 배열 의 크기 입 니 다.문제 데 이 터 는 답 이 유일 하 다 는 것 을 보증 합 니 다. 다시 말 하면 배열 의 앞 k 개의 고주파 요소 의 집합 이 유일 하 다 는 것 입 니 다.너 는 임의의 순서에 따라 답안 을 되 돌려 줄 수 있다.
[문제 풀이 사고 1] map, 작은 지붕 더미
맵 으로 각 요소 가 나타 나 는 횟수 를 기록 하고 정렬 한 후 주파수 가 가장 높 은 k 개 수 를 얻 습 니 다.
class Solution {
     
    public int[] topKFrequent(int[] nums, int k) {
     
        Map<Integer, Integer> map = new HashMap<>();
        for(int temp : nums) {
     
            map.put(temp, map.getOrDefault(temp, 0) + 1);
        }
        int len = map.size();
        int[][] order = new int[len][2];
        int index = 0;
        for(int temp : map.keySet()) {
     
            order[index][0] = temp;
            order[index][1] = map.get(temp);
            index++;
        }
        Arrays.sort(order, (a, b) -> b[1] - a[1]);
        int[] ans = new int[k];
        for(int i = 0; i < k; i++) {
     
            ans[i] = order[i][0];
        }
        return ans;
    }
}

가장 쉬 운 방법 은 '출현 횟수 배열' 에 정렬 하 는 것 이다.그러나 O (N) 개의 서로 다른 출현 횟수 가 있 을 수 있 기 때문에 전체적인 알고리즘 복잡 도 는 O (NLogN) 에 달 하고 제목 의 요 구 를 만족 시 키 지 못 한다.쌓 인 사상 개선 을 이용 할 수 있 습 니 다. k 크기 의 작은 지붕 을 유지 한 다음 에 '출현 횟수 배열' 을 옮 겨 다 닐 수 있 습 니 다.
  • 쌓 인 요소 의 개수 가 k 보다 적 으 면 쌓 인 요소 에 직접 삽입 할 수 있다.
  • 쌓 인 요소 의 개수 가 k 와 같 으 면 쌓 인 지붕 과 현재 나타 난 횟수 의 크기 를 검사 합 니 다.만약 에 쌓 인 지붕 이 더 크다 면 적어도 k 개의 숫자 가 현재 값 보다 많이 나타 나 기 때문에 현재 값 을 버 리 는 것 을 의미한다.그렇지 않 으 면 덤 프 를 꺼 내 현재 값 을 덤 프 에 삽입 합 니 다.

  • 옮 겨 다 니 기 가 완 료 된 후에 쌓 인 요 소 는 '출현 횟수 배열' 의 앞 k 큰 값 을 대표 합 니 다.다음은 우선 대기 열 이라는 기 존 유형 을 사용 하여 이 루어 졌 으 며, 작은 지붕 더 미 를 수 동 으로 실현 할 수 있 습 니 다.
    class Solution {
         
        public int[] topKFrequent(int[] nums, int k) {
         
            Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
            for (int num : nums) {
         
                occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
            }
    
            // int[]             ,               
            PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
         
                public int compare(int[] m, int[] n) {
         
                    return m[1] - n[1];
                }
            });
            for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
         
                int num = entry.getKey(), count = entry.getValue();
                if (queue.size() == k) {
         
                    if (queue.peek()[1] < count) {
         
                        queue.poll();
                        queue.offer(new int[]{
         num, count});
                    }
                } else {
         
                    queue.offer(new int[]{
         num, count});
                }
            }
            int[] ret = new int[k];
            for (int i = 0; i < k; ++i) {
         
                ret[i] = queue.poll()[0];
            }
            return ret;
        }
    }
    
    class Solution {
         
        public int[] topKFrequent(int[] nums, int k) {
         
            Map<Integer, Integer> map = new HashMap<>();
            for (int n : nums){
         
                map.put(n, map.getOrDefault(n, 0) + 1);
            }
            PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((e1, e2) -> e2.getValue() - e1.getValue());
            queue.addAll(map.entrySet());
            int[] ans = new int[k];
            for (int i = 0; i < k && !queue.isEmpty(); ++i){
         
                ans[i] = queue.poll().getKey();
            }
            return ans;
        }
    }
    

    수 동 으로 쌓 기
    class Solution {
         
        //                
        Map<Integer , Integer> map = new HashMap<>();
        
        public int[] topKFrequent(int[] nums, int k) {
             
            int[] heap = new int[k];
            for(int i : nums){
         
                map.put(i , map.getOrDefault(i,0) + 1);
            }
            Iterator it = map.keySet().iterator();
            int i = 0;
            while(it.hasNext()){
         
                //          k  ,        k ,     
                if( i < k){
         
                    heap[i] = (Integer)it.next();
                    i++;
                    if(i == k){
         
                        for(int j = k/2 -1 ; j >= 0 ; j--){
         
                            heapSort(heap,j);
                        }
                    }
                }else{
            //       ,               ,      ,    ,       
                    int key = (Integer)it.next(); 
                    if(map.get(key) > map.get(heap[0])) heap[0] = key;
                    heapSort(heap , 0);
                }
                
            }
            return heap;
        }
        
        //     
        //  ,                ,     map    value
        public void heapSort(int[] heap , int i){
         
            int temp = heap[i];
            for(int j = 2*i + 1 ; j < heap.length ; j = 2*j + 1){
         
                if(j+1 < heap.length && map.get(heap[j+1]) < map.get(heap[j])) j++;
                if(map.get(heap[j]) < map.get(temp)){
         
                    heap[i] = heap[j];
                    i = j;
                }else break;
            }
            heap[i] = temp;
        }
    }
    

    [문제 풀이 사고 2] 빨리 배열 (연구 대기)
    배열 arr [l... r] 를 빠르게 정렬 하 는 과정 에서 먼저 배열 을 두 부분 arr [i... q - 1] 과 arr [q + 1... j] 로 나 누고 arr [i... q - 1] 의 모든 값 이 arr [q] 를 초과 하지 않 으 며 arr [q + 1.. j] 의 모든 값 이 arr [q] 보다 크다.k 와 왼쪽 하위 배열 arr [i... q - 1] 의 길이 (q - i) 의 크기 관계 에 따라:
  • k ≤ q − i 라면 배열 arr [l.. r] 앞 k 큰 값 은 하위 배열 arr [i... q - 1] 앞 k 큰 값 과 같다.
  • 그렇지 않 으 면 배열 arr [l... r] 앞 k 의 큰 값 은 왼쪽 하위 배열 의 모든 요소 와 같 고 오른쪽 하위 배열 arr [q + 1... j] 중 앞 k - (q - i) 의 큰 값 을 더 합 니 다.
  • class Solution {
         
        public int[] topKFrequent(int[] nums, int k) {
         
            Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
            for (int num : nums) {
         
                occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
            }
    
            List<int[]> values = new ArrayList<int[]>();
            for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
         
                int num = entry.getKey(), count = entry.getValue();
                values.add(new int[]{
         num, count});
            }
            int[] ret = new int[k];
            qsort(values, 0, values.size() - 1, ret, 0, k);
            return ret;
        }
    
        public void qsort(List<int[]> values, int start, int end, int[] ret, int retIndex, int k) {
         
            int picked = (int) (Math.random() * (end - start + 1)) + start;
            Collections.swap(values, picked, start);
            
            int pivot = values.get(start)[1];
            int index = start;
            for (int i = start + 1; i <= end; i++) {
         
                if (values.get(i)[1] >= pivot) {
         
                    Collections.swap(values, index + 1, i);
                    index++;
                }
            }
            Collections.swap(values, start, index);
    
            if (k <= index - start) {
         
                qsort(values, start, index - 1, ret, retIndex, k);
            } else {
         
                for (int i = start; i <= index; i++) {
         
                    ret[retIndex++] = values.get(i)[0];
                }
                if (k > index - start + 1) {
         
                    qsort(values, index + 1, end, ret, retIndex, k - (index - start + 1));
                }
            }
        }
    }
    

    좋은 웹페이지 즐겨찾기