매우 큰 파일에서 가장 많이 발생하는 요소 찾기


12

나는이 인터뷰 질문에 많은 질문을 들었고 좋은 답변이 무엇인지에 대한 의견을 얻기를 희망했습니다. 이것을하기 위해?

많은 메모리를 사용하기 때문에 맵에서 트랙을 반복하고 유지하는 것은 좋은 생각이 아니며,이 질문이 제기되면 파일이 이미 존재하기 때문에 항목이 들어올 때 트랙을 유지하는 것이 가장 좋은 옵션이 아닙니다.

다른 생각은 파일을 여러 스레드에서 반복하고 처리하여 분할 한 다음 그 결과를 결합하는 것을 포함했지만 맵의 메모리 문제는 여전히 존재합니다.


2
파일의 요소는 무엇입니까? 그들은 끈입니까? 요소에 문자를 사용하면 맵에 메모리 문제가 없습니다. 요소가 단어라면 다시 문제가되지 않는다고 생각합니다. 가능한 모든 부분 문자열이 있다면 문제가 생길 수 있습니다.
Nejc

1
조건이 "전체 요소의 절반 이상으로 나타나는 요소"인 경우 선형 솔루션이있었습니다.
st0le

나는 요소가 보통 문자열이라고 믿습니다. 그러나 나는지도가 어떻게 문제가되지 않는지 알지 못한다. 모든 요소가 고유 한 최악의 경우 메모리 요구 사항을 두 배로 늘리지 않았습니까?
Pat

1
Boyer-Moore 다수 후보 알고리즘이 적용 가능한 경우, 선형 시간으로 실행되고 제자리에 있습니다.
Juho

답변:


6

당신이있을 때 정말 큰 파일과 많은 그것의 요소를하지만, 가장 일반적인 요소는 매우 일반적이다 - 발생 시간의 비율을 - 당신은 공간과 선형 시간에서 찾을 수 있습니다 O ( K ) (단어 O ( ) 표기법 의 상수 는 매우 작습니다. 해시와 같은 보조 항목에 대한 저장소를 계산하지 않으면 기본적으로 2입니다. 또한 파일은 한 번에 한 요소 씩 순서대로 처리되고 알고리즘은 "돌아 보지"않기 때문에 외부 저장소와 함께 작동합니다. 이를 수행하는 한 가지 방법은 Misra와 Gries의 클래식 알고리즘을 사용하는 것입니다. 강의 노트를 참조하십시오.>1/kO(k)O(). 이 문제는 이제 헤비 타자 문제로 알려져 있습니다 (빈번한 요소는 헤비 타자입니다).

가정 가장 빈번한 요소 나타 에 대한 시간의 비율 K 소수 강한 보일 수 있지만이 방법에 필요하다! 즉, 파일에 순차적으로 액세스 할 수 있고 (파일이 엄청나게 무작위로 액세스하는 경우 비용이 너무 많이 드는 경우) 항상 일정한 패스 수에서 가장 빈번한 요소를 찾는 알고리즘은 요소 수에서 공간을 선형으로 사용합니다 . 따라서 입력에 대해 가정하지 않으면 해시 테이블을 이길 수 없습니다. 가장 빈번한 요소가 매우 빈번하다는 가정은 아마도 부정적인 결과를 피하는 가장 자연스러운 방법 일 것입니다.>1/kk

여기에 대한 스케치가 있습니다. 즉, 절반 이상의 시간에 단일 요소가있는 경우입니다. 이 특별한 경우는 과반수 투표 알고리즘으로 알려져 있으며 Boyer와 Moore에 의한 것입니다. 우리는 하나의 요소와 하나의 수를 유지합니다. 카운트를 1로 초기화하고 파일의 첫 번째 요소를 저장하십시오. 그런 다음 파일을 순서대로 처리하십시오.k=2

  • 파일의 현재 요소가 저장된 요소와 동일하면 개수를 1 씩 증가시킵니다.
  • 파일의 현재 요소가 저장된 요소와 다른 경우 카운트를 1 씩 줄입니다.
  • 업데이트 된 카운트가 0이면, 저장된 요소를 "차기"하고 파일의 현재 요소를 저장하고; 카운트를 1로 늘리십시오
  • 파일의 다음 요소로 진행

이 절차에 대해 조금만 생각하면 "주요"요소가 존재하는 경우, 즉 절반 이상이 발생하는 경우 전체 파일이 처리 된 후 해당 요소가 저장된 요소가된다는 것을 확신 할 수 있습니다.

kk1k1kk

k11/kO(k)

k1/kk1


Boyer-Moore 또는 Misra-Gries-Demaine 알고리즘을 사용할 수 없습니다. 언급 된 문제는 다릅니다. 대부분의 요소를 검색하는 것이 아니라 모든 요소의 발생 수가> = 인 요소를 찾으십시오. 간단한 반례가 있습니다. 하자 N 요소의 총 개수와 같은 것일 N = 2K + 1 . 첫 번째 k 요소는 0, 다음 k 요소는 1, 마지막 요소는 2로 둡니다. Boyer-Moore 알고리즘은 마지막 요소 인 2를 잠재적 과반수 후보로보고합니다. 그러나이 특정한 경우 출력은 0 또는 1이어야합니다.
Massimo Cafaro

O(1)Ω(n)

방금 잘못된 가정을하면 잘못된 결과를 얻을 수 있다고 지적했습니다. 더 작은 메모리 공간과 잠재적으로 잘못된 결과 또는 정확한 결과는 더 많은 메모리 비용이 듭니다. 잠재적으로 잘못된 결과를 선택 해야하는 경우 실제로 알지 못하는 것으로 가정하고 Boyer-Moore 대신 무작위 알고리즘을 사용합니다.
Massimo Cafaro

@MassimoCafaro는 당신이해야 할 절충이 아닙니다. 내가 지적 파일을 통해 쉽게를 검증을 하나의 패스를 가정이 만족되는 경우!
Sasho Nikolov

@MassimoCafaro 그리고 이것은 사소한 해결책 일뿐입니다! 추가 통과없이 CM 스케치를 사용하여 높은 확률로 가정을 검증 할 수 있습니다.
Sasho Nikolov

3

물론 Nejc가 이미 제안한 것처럼 파일을 이동할 때 해시 맵을 유지하고 요소 발생 카운터를 저장하는 것이 확실한 대답입니다. 이것이 (시간 복잡성 측면에서) 최적의 솔루션입니다.

Θ(nlogn).


허프만 인코딩 방식에 대해 더 자세히 설명해 주시겠습니까? 허프만 엔코더를 전에 작성했지만 잠시 동안이 경우 정확히 어떻게 사용 하시겠습니까?
Pat

@Pat 아침에 너무 이른 부분이었고 입력을 압축하는 것이 합리적이라고 생각했습니다.
Jernej

1

가장 일반적인 요소가 실질적인 여백으로 다음 공통 요소보다 더 일반적이고 다른 요소의 수가 파일 크기에 비해 적은 경우 무작위로 몇 개의 요소를 샘플링하고 가장 일반적인 요소를 샘플에서 반환 할 수 있습니다.


또한 여러 번 발생하는 소수의 요소가있는 경우 샘플링을 통해 해당 요소를 찾은 다음 이러한 요소 만 정확하게 계산할 수 있습니다.
최대
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.