나는 최근에 내가 질문 아래 질문을 받았다 인터뷰를했다 그리고 그것은 나에게 아주 쉽게 소리를하지만 마지막에 나를 위해 까다로운되었다.
모든 폴더와 그 하위 폴더에있는 파일이 많이 있습니다. 각 파일은 각 라인에 숫자를 많이해야합니다. 루트 폴더 감안할 때, 나는 모든 파일에서 100 대 번호를 찾을 필요가있다. 나는 아래의 해결책을했다 :
- 라인으로 모든 파일 라인을 읽어보십시오.
- 배열 목록의 각 수를 저장합니다.
- 내림차순으로 정렬합니다.
- 이제 목록에서 첫 번째 k 개의 번호를 얻을.
그러나 면접관이의 시간 복잡도가 될 것입니다 무엇을 나에게 물었다. 나는 우리가 그것을 정렬되기 때문에이 그래서 말했다 될거야 O (nlogn) 그리고 그는 우리가 프로그램보다 개선 할 수있는 방법을 물어? 당신은 메모리의 모든 내용을 저장하고 있기 때문에 다음 정렬 - 만약에 당신이 할 수없는 메모리에 맞게 모든 것을?
그때 나는 혼동하고이 문제를 아래 해결하기 위해 더 나은 / 효율적인 방법이 있다면 알아낼 수 없었다. 그는 효율적인 코드를 작성하는 나를 원했다. 이러한 목표를 달성 할 수있는 더 좋은 방법이 있나요?
아래는 내가 생각 해낸 내 원래의 코드는 다음과 같습니다
private static final List<Integer> numbers = new ArrayList<>();
public static void main(String[] args) {
int k = 100;
List<Integer> numbers = findKLargest("/home/david");
// sort in descending order
Collections.sort(numbers, Collections.reverseOrder());
List<Integer> kLargest = new ArrayList<>();
int j = 0;
// now iterate all the numbers and get the first k numbers from the list
for (Integer num : numbers) {
j++;
kLargest.add(num);
if (j == k) {
break;
}
}
// print the first k numbers
System.out.println(kLargest);
}
/**
* Read all the numbers from all the files and load it in array list
* @param rootDirectory
* @return
*/
private static List<Integer> findKLargest(String rootDirectory) {
if (rootDirectory == null || rootDirectory.isEmpty()) {
return new ArrayList<>();
}
File file = new File(rootDirectory);
for (File entry : file.listFiles()) {
if (entry.isDirectory()) {
numbers.addAll(findKLargest(entry.getName()));
} else {
try (BufferedReader br = new BufferedReader(new FileReader(entry))) {
String line;
while ((line = br.readLine()) != null) {
numbers.add(Integer.parseInt(line));
}
} catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
}
}
return numbers;
}
대신 모든 저장하는 N을 값 (전체 모든 파일에서 숫자 계산)하고 정렬 만 100 값을 저장할 수 있습니다 - 모든 순간에 가장 큰 것들.
이 작업을위한 편리하고 빠른 데이터 구조 - 우선 순위 큐 (보통에 따라 바이너리 힙 ). 생성 분 은 가기 힙보다 큰지마다 새로운 값 확인을 위해 그 후, 제 100 개 값을 -heap. 그렇다면 - 제거 탑, 새로운 항목을 삽입합니다.
공간의 복잡성은 O(K)
시간 복잡도는, O(NlogK)
여기, K=100
그래서 복잡성으로 평가 될 수 O(1)
및 O(N)
(생략 일정 기간)
그것이 작동하는 방법 파이썬 예를 표시합니다 :
import heapq, random
pq = [random.randint(0, 20) for _ in range(5)] #initial values
print(pq)
heapq.heapify(pq) #initial values ordered in heap
print(pq)
for i in range(5):
r = random.randint(0, 20) # add 5 more values
if r > pq[0]:
heapq.heappop(pq)
heapq.heappush(pq, r)
print(r, pq)
[17, 22, 10, 1, 15] //initial values
[1, 15, 10, 22, 17] //heapified, smallest is the left
29 [10, 15, 17, 22, 29] //29 replaces 1
25 [15, 22, 17, 29, 25] //25 replaces 10
14 [15, 22, 17, 29, 25] //14 is too small
8 [15, 22, 17, 29, 25] //8 is too small
21 [17, 21, 25, 29, 22] //21 is in the club now