문제

이것은 CS 담당자가 이론을 빛나게 하는 연습입니다.

요소가 포함된 컨테이너가 2개 있다고 가정해 보세요.폴더, URL, 파일, 문자열 등은 실제로 중요하지 않습니다.

추가된 것과 제거된 것을 계산하는 AN 알고리즘은 무엇입니까?

알아채다:이 문제를 해결할 수 있는 방법이 여러 가지인 경우 분석하고 투표할 수 있도록 답변당 하나씩 게시해 주세요.

편집하다:모든 답변은 4개의 컨테이너로 문제를 해결합니다.초기 2개만 사용 가능한가요?

도움이 되었습니까?

해결책

두 개의 고유 항목 목록이 있고 순서는 중요하지 않다고 가정하면 둘 다 목록이 아닌 세트로 생각할 수 있습니다.

목록 A를 하나의 원으로, 목록 B를 다른 원으로 사용하는 벤 다이어그램을 생각하면 이 둘의 교차점이 상수 풀입니다.

A와 B 모두에서 이 교차점의 모든 요소를 ​​제거하고 A에 남아 있는 모든 요소는 삭제되고 B에 남아 있는 요소는 추가됩니다.

따라서 A를 반복하여 B의 각 항목을 찾습니다.찾으면 A와 B 모두에서 제거하십시오.

그러면 A는 삭제된 항목의 목록이고, B는 추가된 항목의 목록입니다.

제 생각에는...

[편집] 좋습니다. 새로운 "컨테이너 2개만" 제한을 적용해도 여전히 동일합니다.

foreach( A ) { 
  if( eleA NOT IN B ) {
    DELETED
  }
}
foreach( B ) {
  if( eleB NOT IN A ) {
    ADDED
  }
}

그런 다음 새 목록을 생성하거나 이전 목록을 삭제하지 않습니다. 하지만 이전 예제와 마찬가지로 시간이 더 오래 걸립니다. 짧은 목록을 반복하고 더 긴 목록에서 요소를 제거하면 됩니다.여기서 두 목록을 모두 수행해야 합니다.

내 첫 번째 솔루션은 4개의 컨테이너를 사용하지 않고 2개만 파괴했다고 주장하겠습니다 ;-)

다른 팁

나는 한동안이 작업을 수행하지 않았지만 알고리즘이 이렇게 생각합니다 ...

sort left-list and right-list
adds = {}
deletes = {}
get first right-item from right-list
get first left-item from left-list
while (either list has items)
  if left-item < right-item or right-list is empty
    add left-item to deletes
    get new left-item from left-list
  else if left-item > right-item or left-list is empty
    add right-item to adds
    get new right-item from right-list
  else
    get new right-item from right-list
    get new left-item from left-list

왼쪽 목록과의 오른쪽 목록의 관계와 관련하여 삭제 제거 된 항목이 포함되어 있습니다 추가합니다 이제 새 항목이 포함되어 있습니다.

Joe가 말한 것. 또한 목록이 메모리에 너무 커지면 외부 파일 분류 유틸리티 또는 병합 정렬을 사용하십시오.

누락 된 정보 : 추가/제거 된 방법은 어떻게 정의합니까? 예 : 목록 (A 및 B)이 서버 A 및 서버 B에 동일한 디렉토리를 표시하는 경우 동기화됩니다. 이제 10 일 동안 기다리면 목록을 다시 생성하고 비교하면 무언가가 제거되었는지 어떻게 알 수 있습니까? 나는 할 수 없다. 서버 A에 파일이 서버 B 및/또는 다른 방식으로 파일이 있다고 말할 수 있습니다. 파일이 서버 A에 추가 되었기 때문에 (따라서 파일이 b에서 찾을 수 없음) 또는 서버 B에서 파일이 삭제되었는지 여부 (따라서 파일은 b에서 파일을 찾을 수 없습니다. 더 이상)는 파일 이름 목록만으로 결정할 수없는 것입니다.

내가 제안한 솔루션의 경우, 나는 당신이 Old라는 목록 하나와 New라는 목록 하나가 있다고 가정합니다. 오래되었지만 새로 발견되지 않은 모든 것이 제거되었습니다. 새로 발견되었지만 이전에는없는 모든 것이 추가되었습니다 (예 : 동일한 서버에서 동일한 디렉토리의 내용은 다른 날짜로 작성되었습니다).

또한 중복이 없다고 가정 할 것입니다. 즉, 어느 목록의 모든 항목이 다음과 같은 의미에서 독특하다는 것을 의미합니다. 더 작은 또는 더 큰 내가 비교하는 것보다, 그리고 결코 같지 않습니다. 예를 들어 줄을 다룰 때는 사전 어휘를 비교할 수 있으며 같은 문자열은 목록에서 두 번 두 번이 아닙니다.

이 경우 가장 간단한 (반드시 최상의 솔루션은 아닙니다)는 다음과 같습니다.

  1. 이전 목록을 정렬하십시오. 예 : 목록이 문자열로 구성되면 알파벳순으로 정렬하십시오. 정렬이 필요합니다. 이진 검색을 사용하여 목록에서 객체를 신속하게 찾을 수 있기 때문에 (또는 신속하게 결정하기 위해서는 목록에 전혀 존재하지 않습니다). 목록이 분류되지 않은 경우 객체를 찾는 데 O (N)의 복잡성이 있습니다 (목록의 모든 단일 항목을 살펴 봐야합니다). 목록이 정렬되면 복잡성은 O (log n)에만 해당됩니다. 모든 목록의 항목을 일치 시키면 목록에있는 항목의 50%를 일치하지 않기 때문에 항상 일치하지 않을 수 있습니다. 목록에 100 개의 항목이 있더라도 항목을 찾거나 항목이 목록에 없음을 감지하는 것은 최대 7 개의 테스트 (또는 어쨌든 100보다 훨씬 작음)를 사용합니다. 새 목록을 정렬 할 필요는 없습니다.

  2. 이제 우리는 목록 제거를 수행합니다. 새 목록의 모든 항목에 대해 이전 목록 에서이 항목을 찾으십시오 (이진 검색 사용). 항목이 발견되면 이전 목록 에서이 항목을 제거하고 또한 새 목록에서 제거하십시오. 이것은 또한 목록이 더 작아 질수록 제거가 진행되므로 조회가 더 빨라지고 점점 더 빨라질 것입니다. A 목록에서 항목을 제거하는 것은 목록의 올바른 정렬 순서에 영향을 미치지 않기 때문에 제거 단계에서 이전 목록을 리조트 할 필요가 없습니다.

  3. 제거가 끝나면 두 목록이 모두 비어있을 수 있으며,이 경우 동일했습니다. 비어 있지 않은 경우 기존 목록에있는 모든 항목은 새 목록에 누락 된 항목입니다 (그렇지 않으면 제거했습니다). 제거 된 항목. 새 목록에있는 모든 항목은 이전 목록에 있지 않은 항목입니다 (다시, 우리는 다른 방법으로 제거했습니다). 추가 항목.

목록의 개체가 "고유"입니까? 이 경우 먼저 두 개의 맵 (해시 맵)을 빌드 한 다음 목록을 스캔하고 맵에서 모든 객체를 조회합니다.

map1
map2
removedElements
addedElements

list1.each |item|
{
    map1.add(item)
}
list2.each |item|
{
    map2.add(item)
}
list1.each |item|
{
    removedElements.add(item) unless map2.contains?(item)
}
list2.each |item|
{
    addedElements.add(item) unless map1.contains?(item)
}

Ruby와 Java를 혼합 한 끔찍한 메타 언어 혼합에 대해 죄송합니다 : -P

결국 제거 요소 List1에 속하는 요소가 포함되지만 List2는 아닙니다. 추가 요소 List2에 속하는 요소가 포함됩니다.

지도/사전에서의 조회가 일정하게 간주 될 수 있기 때문에 전체 작업 비용은 O (4*N)입니다. 반면에 목록에서 각 요소를 검색하는 선형/이진은 O (n^2)를 만듭니다.

편집하다: 두 번째로 마지막 체크를 두 번째 루프로 옮기는 두 번째 생각에서 루프 중 하나를 제거 할 수 있습니다 ... 그러나 그것은 못 생겼습니다 ... :)

list1.each |item|
{
    map1.add(item)
}
list2.each |item|
{
    map2.add(item)
    addedElements.add(item) unless map1.contains?(item)
}
list1.each |item|
{
    removedElements.add(item) unless map2.contains?(item)
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top