이 면접 질문을 받았습니다 :
40 억 개의 정수를 가진 입력 파일이 주어지면 파일에 포함되지 않은 정수를 생성하는 알고리즘을 제공하십시오. 1GB 메모리가 있다고 가정하십시오. 10MB의 메모리 만있는 경우 수행 할 작업을 추적하십시오.
내 분석 :
파일 크기는 4 × 10 9 × 4 bytes = 16GB입니다.
외부 정렬을 수행 할 수 있으므로 정수 범위를 알려줍니다.
내 질문은 정렬 된 큰 정수 세트에서 누락 된 정수를 감지하는 가장 좋은 방법은 무엇입니까?
내 이해 (모든 답변을 읽은 후) :
32 비트 정수에 대해 이야기하고 있다고 가정하면 2 32 = 4 * 10 9 개의 고유 정수가 있습니다.
사례 1 : 1GB = 1 * 10 9 * 8 비트 = 80 억 비트 메모리가 있습니다.
해결책:
하나의 고유 한 정수를 나타내는 하나의 비트를 사용하면 충분합니다. 우리는 정렬 할 필요가 없습니다.
이행:
int radix = 8;
byte[] bitfield = new byte[0xffffffff/radix];
void F() throws FileNotFoundException{
Scanner in = new Scanner(new FileReader("a.txt"));
while(in.hasNextInt()){
int n = in.nextInt();
bitfield[n/radix] |= (1 << (n%radix));
}
for(int i = 0; i< bitfield.lenght; i++){
for(int j =0; j<radix; j++){
if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j);
}
}
}
사례 2 : 10MB 메모리 = 10 * 10 6 * 8 비트 = 8 천만 비트
해결책:
가능한 모든 16 비트 접두사에 대해 2 16 개의 정수 = 65536이 있으며 2 16 * 4 * 8 = 2 백만 비트가 필요합니다. 65536 버킷을 빌드해야합니다. 각 버킷마다 모든 가능성을 보유하는 4 바이트가 필요합니다. 최악의 경우 40 억 정수가 모두 동일한 버킷에 속하기 때문입니다.
- 파일을 통한 첫 번째 통과를 통해 각 버킷의 카운터를 만듭니다.
- 버킷을 스캔하고 적중률이 65536 미만인 첫 번째 버킷을 찾으십시오.
- 2 단계에서 파일의 두 번째 패스를 통해 높은 16 비트 접두사가있는 새 버킷을 빌드하십시오.
- 3 단계에서 빌드 한 버킷을 스캔하고 적중하지 않은 첫 번째 버킷을 찾으십시오.
코드는 위의 코드와 매우 유사합니다.
결론 : 파일 전달을 늘려 메모리를 줄입니다.
늦게 도착하는 사람들을위한 설명 : 질문에 따르면, 질문에 따르면 파일에 포함되지 않은 정수가 정확히 하나 있다고 말하지는 않습니다. 적어도 대부분의 사람들이 그것을 해석하는 방식이 아닙니다. 주석 스레드의 많은 의견이 있다 하지만, 작업의 변화에 대해. 불행하게도 주석 도입 이후 저자에 의해 삭제 된 코멘트 스레드에, 그래서 지금은 오해 다 그것에 고아 응답 것 같습니다. 매우 혼란 스럽습니다. 죄송합니다.