2010-05-04 5 views
2

HashMap에 저장된 Integer 객체의 ArrayList가 여러 개 있습니다.각 목록에 나타나는 모든 숫자 찾기

각 목록에 나타나는 모든 숫자 (정수 개체)의 목록 (ArrayList)을 가져 오려고합니다.

내 생각은 지금까지입니다 :

  1. 각 ArrayList를 통해 반복 처리와는 HashSet의
    • 이이 목록에있는 모든 값의 "목록"우리에게 줄 것이다에 모든 값을 추가하는 듯했으나 한번만의 반복과 함께 HashSet의
      2.1 내지
  2. 반복 처리는 ArrayList.contains()
    수행 2.2 어떤 ArrayList도 false를 반환하지 않으면 최종 값이 모두 들어있는 "마스터 목록"에 숫자를 추가합니다.

더 빠르고 더 효율적으로 생각해 낼 수 있다면 재미있는 것은 내가 쓴 것처럼 합리적으로 좋은 해결책을 생각해 냈습니다. 하지만 다른 사람에게 유용하기 때문에 나는 여전히 게시 할 것입니다.

물론 더 나은 방법이 있다면 알려주세요.

+0

첫 용액 것 O (n) 시간에 추가 저장 공간없이 작업하십시오. – Rubys

+0

내 직감에 약간의 엄격함을 추가해 주셔서 감사합니다.) – Ankur

+1

두 목록이 [1, 1, 2]이고 [1, 1, 3] 인 경우 출력이 [1, 1] 또는 간단하게 [1]가 되겠습니까? 즉 중복 된 항목을 보유 하시겠습니까? – Adamski

답변

0
  1. 는 제 List에서 Set (예컨대 HashSet)을 만든다. 나머지 각 목록
  2. : 작은 set.retainAll (list)list 둘 경우 set
    • 전화 충분히
    • 그렇지 않으면 2 단계의 두 번째 변형을 임계 값 set.retainAll (new HashSet <Integer> (list))

내가 말할 수없는 후 호출합니다. 더 빠르지 만, 아마도 > 20 크기 정도라고 생각합니다. 귀하의 목록이 모두 작 으면이 수표로 귀찮게하실 수 없습니다.

O (*) 부분뿐만 아니라 요소에 대해서도 신경을 쓰면 아파치 모음은 더 효율적인 정수 전용 구조를 가지고 있음을 기억합니다.

+0

Ankur의 첫 번째 솔루션의 무서운 돌연변이로 새로운 HashSet을 만듭니다 맵의 모든 목록에 대해 기본적으로 O (n^2) 공간을 낭비하게됩니다. 이것은 자바입니다, GC는 비 결정적입니다. GC는 알 수없는 양의 시간이 지나면 사용되지 않은 해시 집합을 수집 할 수 있습니다. 즉, O (n^2) 개의 메모리 양이 할당되어 있지만 사용되지는 않습니다. 또는 다른 말로하면 낭비입니다. – Rubys

+1

@Rubys : 어디서 O (n^2)를 얻을지 모르겠다. 명확하지 않은 경우'set '이 첫 번째 단계에서 생성 된 것입니다. 나는. 루프 전체에서 동일합니다. 2a 단계에서 "중간"세트를 만드는 것은 목록에서 (예상) O (1) 대 O (n)이므로 해시를 설정하면 검색 속도가 빨라집니다 ('retainAll'에서). – doublep

+0

우리가 아는 한 목록과 세트는 결코 작을 수 없으며 매 반복마다 새로운 HashSet을 생성합니다. 그 해트트는 그 자체로 O (n) 공간을 차지할 것입니다. 그것은 O (n^2)가 아니고 그것은 나쁘고 O (nm) 공간입니다. n은 가장 큰 목록이고 m은 원래 집합에있는 목록의 수입니다. 각 반복마다 O (n) 공간을 소비하는 새로운 해시 세트를 만듭니다. 당신은 그 포인터를 다른 곳에 두어야하기 때문에. 따라서 모든 반복을 함께하면 O (nm) SPACE를 사용하게됩니다. 시간은 여전히 ​​멋질 것입니다. – Rubys

2

당신은 1 단계 변경해야합니다 : 를 - (이 짧은 목록에없는 경우 ... 그것은 모든 목록에없는)에 포함되어 다음 전화를 대신 HashSet에의

을 짧은 목록을 사용하여

public class TestLists { 

    private static List<List<Integer>> listOfLists = new ArrayList<List<Integer>>(); 

    private static List<Integer> filter(List<List<Integer>> listOfLists) { 

     // find the shortest list 
     List<Integer> shortestList = null; 
     for (List<Integer> list : listOfLists) { 
      if (shortestList == null || list.size() < shortestList.size()) { 
       shortestList = list; 
      } 
     } 

     // create result list from the shortest list 
     final List<Integer> result = new LinkedList<Integer>(shortestList); 

     // remove elements not present in all list from the result list 
     for (Integer valueToTest : shortestList) { 
      for (List<Integer> list : listOfLists) { 
       // no need to compare to itself 
       if (shortestList == list) { 
        continue; 
       } 

       // if one list doesn't contain value, remove from result and break loop 
       if (!list.contains(valueToTest)) { 
        result.remove(valueToTest); 
        break; 
       } 
      } 
     } 

     return result; 
    } 


    public static void main(String[] args) { 
     List<Integer> l1 = new ArrayList<Integer>(){{ 
      add(100); 
      add(200); 
     }}; 
     List<Integer> l2 = new ArrayList<Integer>(){{ 
      add(100); 
      add(200); 
      add(300); 
     }}; 
     List<Integer> l3 = new ArrayList<Integer>(){{ 
      add(100); 
      add(200); 
      add(300); 
     }}; 
     List<Integer> l4 = new ArrayList<Integer>(){{ 
      add(100); 
      add(200); 
      add(300); 
     }}; 
     List<Integer> l5 = new ArrayList<Integer>(){{ 
      add(100); 
      add(200); 
      add(300); 
     }}; 
     listOfLists.add(l1); 
     listOfLists.add(l2); 
     listOfLists.add(l3); 
     listOfLists.add(l4); 
     listOfLists.add(l5); 
     System.out.println(filter(listOfLists)); 

    } 

} 
,691,363 : 다른 목록 및

... 일부 코드를 하나 false를 반환하는 즉시 값을 제거 (이 값에 대한 추가 시험 생략) 짧은 목록에 답을 포함 끝에

을210

4

나는 당신의 목표를 이해하고 있는지 확신하지 못합니다.당신이 목록 < 정수> 개체의 컬렉션의 교차을 찾고자한다면, 당신은 다음과 같은 작업을 수행 할 수

public static List<Integer> intersection(Collection<List<Integer>> lists){ 
    if (lists.size()==0) 
     return Collections.emptyList(); 

    Iterator<List<Integer>> it = lists.iterator(); 
    HashSet<Integer> resSet = new HashSet<Integer>(it.next()); 
    while (it.hasNext()) 
     resSet.retainAll(new HashSet<Integer>(it.next())); 

    return new ArrayList<Integer>(resSet); 
} 

이 코드는 총 항목 수에 선형 시간에 실행됩니다. 사실 이것은 HashSet을 사용하기 때문에 평균 선형 시간입니다.

또한 루프에서 ArrayList.contains()를 사용하면이 메서드가 일정 시간에 실행되는 HashSet.contains()와 달리 선형 시간으로 실행되기 때문에 이차 복잡성이 발생할 수 있습니다.

+1

아마도 while 루프에서도 resSet에 대한 빈 검사를 던질 가치가 있습니다. – Carl

+0

오, 그리고 각 it.next()에 대한 새로운 해시 세트를 구성 할 필요가 없습니다. retainAll은 콜렉션에서 작동하며 it.next()의 중복 요소는 작업에 영향을 미치지 않습니다. – Carl

+0

편집 : retainAll의 일부 사례에는 약간의 비용 절감 효과가 있다고 가정합니다. 그러나이 경우 특히 맞춤 메소드가 순서에있을 수 있습니다. – Carl

0

Google 컬렉션 Multiset을 사용하면이 (표현형) 칵테일을 만듭니다 (비록 Eyal's answer도 좋지만). 다른 시간대와 비교해 볼 때 시간/기억력면에서는 효과가 없을 지 모르지만, 그 일은 매우 명확합니다. 목록을 가정

자체 내에 중복 포함하지 :

Multiset<Integer> counter = HashMultiset.create(); 
int totalLists = 0; 
// for each of your ArrayLists 
{ 
counter.addAll(list); 
totalLists++; 
} 

List<Integer> inAll = Lists.newArrayList(); 

for (Integer candidate : counter.elementSet()) 
    if (counter.count(candidate) == totalLists) inAll.add(candidate);` 

목록은 중복 요소를 포함 할 수있는 경우, 먼저 세트를 통해 전달 될 수 있습니다 : 마지막으로

counter.addAll(list) => counter.addAll(Sets.newHashSet(list)) 

, 이것은 또한 이상적입니다 원하는 경우 나중에 추가 데이터를 원할 수도 있습니다 (예 : 일부 특정 값이 얼마나 잘려나는지).

약간의 Eyal하자 (기본적으로 함께 집합을 통해 목록을 필터링하고 모든 중첩 요소들을 유지하는 단계를 접는) 수정하고 상기보다 경량화 다른 접근법 :

public List<Integer> intersection(Iterable<List<Integer>> lists) { 

Iterator<List<Integer>> listsIter = lists.iterator(); 
if (!listsIter.hasNext()) return Collections.emptyList(); 
Set<Integer> bag = new HashSet<Integer>(listsIter.next()); 
while (listsIter.hasNext() && !bag.isEmpty()) { 
    Iterator<Integer> itemIter = listsIter.next().iterator(); 
    Set<Integer> holder = new HashSet<Integer>(); //perhaps also pre-size it to the bag size 
    Integer held; 
    while (itemIter.hasNext() && !bag.isEmpty()) 
    if (bag.remove(held = itemIter.next())) 
    holder.add(held); 
    bag = holder; 
} 
return new ArrayList<Integer>(bag); 
} 
관련 문제