1. 개요

이 사용방법(예제)에서는 Java를 사용하여 배열에서 가장 큰 k개의 요소찾는 문제에 대한 다양한 솔루션을 구현 합니다. 시간 복잡도를 설명하기 위해 Big-O 표기법을 사용합니다.

2. 무차별 대입 솔루션

이 문제에 대한 무차별 대입 솔루션 은 주어진 배열을 k 번 반복하는 것 입니다. 각 반복 에서 가장 큰 값을 찾습니다 . 그런 다음 배열에서 이 값을 제거하고 출력 List에 넣습니다.

public List findTopK(List input, int k) {
    List array = new ArrayList<>(input);
    List topKList = new ArrayList<>();

    for (int i = 0; i < k; i++) {
        int maxIndex = 0;

        for (int j = 1; j < array.size(); j++) {
            if (array.get(j) > array.get(maxIndex)) {
                maxIndex = j;
            }
        }

        topKList.add(array.remove(maxIndex));
    }

    return topKList;
}

주어진 배열의 크기를 n 이라고 가정하면 이 솔루션의 시간 복잡도는 O(n * k) 입니다. 또한 이것은 가장 비효율적인 솔루션입니다.

3. 자바 컬렉션 접근 방식

그러나 이 문제에 대한 보다 효율적인 솔루션이 있습니다. 이 섹션에서는 Java 컬렉션을 사용하여 두 가지를 설명합니다.

3.1. 트리셋

TreeSetRed-Black Tree 데이터 구조 를 백본으로 가지고 있습니다. 결과적으로 이 집합에 값을 넣으면 비용이 O(log n) 입니다. TreeSet 은 정렬된 컬렉션입니다. 따라서 모든 값을 TreeSet에 넣고 그 중 첫 번째 k추출할 수 있습니다.

public List<Integer> findTopK(List<Integer> input, int k) {
    Set<Integer> sortedSet = new TreeSet<>(Comparator.reverseOrder());
    sortedSet.addAll(input);

    return sortedSet.stream().limit(k).collect(Collectors.toList());
}

이 솔루션시간 복잡도는 O(n * log n) 입니다. 무엇보다 k ≥ log n 일 때 무차별 대입 방식보다 더 효율적이라고 가정합니다 .

TreeSet 에는 중복 항목이 없다는 것을 기억하는 것이 중요합니다 . 결과적으로 솔루션은 고유한 값이 있는 입력 배열에 대해서만 작동합니다.

3.2. 우선순위 큐

PriorityQueue Java 데이터 구조 입니다. 그것의 도움으로 우리는 O(n * log k) 솔루션을 얻을 수 있습니다 . 또한 이것은 이전 솔루션보다 더 빠른 솔루션이 될 것입니다. 명시된 문제로 인해 k 는 항상 배열의 크기보다 작습니다. 따라서 O(n * log k) ≤ O(n * log n)을 의미합니다.

알고리즘 은 주어진 배열을 한 번 반복 합니다. 각 반복에서 힙에 새 요소를 추가합니다. 또한 힙의 크기를 k 보다 작거나 같게 유지합니다 . 따라서 힙에서 추가 요소를 제거하고 새 요소를 추가해야 합니다. 결과적으로 배열을 반복한 후 힙에는 k개의 가장 큰 값 이 포함 됩니다.

public List<Integer> findTopK(List<Integer> input, int k) {
    PriorityQueue<Integer> maxHeap = new PriorityQueue<>();

    input.forEach(number -> {
        maxHeap.add(number);

        if (maxHeap.size() > k) {
            maxHeap.poll();
        }
    });

    List<Integer> topKList = new ArrayList<>(maxHeap);
    Collections.reverse(topKList);

    return topKList;
}

4. 선택 알고리즘

주어진 문제를 해결하는 방법에는 여러 가지가 있습니다. 그리고 이 사용방법(예제)의 범위를 벗어나지만 선형 시간 복잡도를 생성하기 때문에 선택 알고리즘 접근 방식을 사용하는  것이 가장 좋습니다 .

5. 결론

이 사용방법(예제)에서는 배열에서 가장 큰 k개의 요소 를 찾는 몇 가지 솔루션을 설명했습니다 .

평소와 같이 예제 코드는 GitHub 에서 사용할 수 있습니다 .

Generic footer banner