代码之家  ›  专栏  ›  技术社区  ›  Deqing

在不更改元素顺序的情况下删除数组中的重复项

  •  20
  • Deqing  · 技术社区  · 13 年前

    我有一个数组,比如 List<Integer> 139, 127, 127, 139, 130

    如何删除它的重复项并保持其顺序不变?即 139, 127, 130

    12 回复  |  直到 13 年前
        1
  •  29
  •   Maroun    13 年前

    使用的实例 java.util.LinkedHashSet .

    Set<Integer> set = new LinkedHashSet<>(list);
    
        2
  •  7
  •   Andrey Chaschev    13 年前

    使用这一内衬:

    yourList = new ArrayList<Integer>(new LinkedHashSet<Integer>(yourList))
    
        3
  •  7
  •   ZhekaKozlov    6 年前

    没有 LinkedHashSet 开销(使用 HashSet 对于所看到的元素,其稍微快一点):

    List<Integer> noDuplicates = list
            .stream()
            .distinct()
            .collect(Collectors.toList());
    

    请注意,订单由 Stream.distinct() 合同:

    对于有序流,不同元素的选择是稳定的(对于 重复元素,元素在遭遇战中最先出现 订单得以保留。)

        4
  •  2
  •   Maroun    13 年前

    建筑 Set 从您的列表中-“ 不包含重复元素的集合 ":

    Set<Integer> yourSet = new HashSet<Integer>(yourList);
    

    并将其转换回您想要的任何内容。

    注意:如果您想保留订单,请使用 LinkedHashSet 相反

        5
  •  0
  •   Masudul    13 年前

    使用 LinkedHashSet 消除重复并维持秩序。

        6
  •  0
  •   Antoniossss    13 年前

    正如我无法推断的那样,你需要保留插入顺序,这是@Maroun-Maroun写的,使用set,但特殊的实现,比如 LinkedHashSet<E> 威奇做的正是你需要的事情。

        7
  •  0
  •   constpetrov    13 年前

    遍历数组(通过迭代器,而不是foreach)并删除重复项。使用集合查找重复项。

    或

    遍历数组并将所有元素添加到LinkedHashSet中,它不允许重复并保持元素的顺序。 然后清除数组,遍历集合并将每个元素添加到数组中。

        8
  •  0
  •   Sampath Kumar    13 年前

    尽管将ArrayList转换为HashSet可以有效地删除重复项,但如果您需要保留插入顺序,我建议您使用此变体

    //list是一些字符串列表

       Set<String> s = new LinkedHashSet<String>(list);
    

    然后,如果需要返回List引用,可以再次使用转换构造函数。

        9
  •  0
  •   Spektre    13 年前

    有两种方法:

    1. 仅使用唯一int创建新列表

      • (与Maroun-Maroun的回答相同)
      • 你可以用2个嵌套的fors来完成,比如O(n.n/2):

        List<int> src,dst;
        // src is input list
        // dst is output list
        dst.allocate(src.num); // prepare size to avoid slowdowns by reallocations
        dst.num=0;             // start from empty list
        for (int i=0;i<src.num;i++)
         {
         int e=1;
         for (int j=0;i<dst.num;i++)
          if (src[i]==dst[j]) { e=0; break; }
         if (e) dst.add(src[i]);
         }
        
    2. 您可以选择重复的项目并将其删除。。。O(2.n)带有标记的删除

      • 这要快得多,但您需要整个int范围的内存表
      • 如果使用数字<010000>则需要BYTE cnt[10001]
      • 如果使用数字<-1000010000>则需要BYTE cnt[20002]
      • 对于像这样的小范围是可以的,但如果你必须使用32位范围,它将需要4GB!!!
      • 使用比特打包,每个值可以有2个比特,所以只有1GB,但这对我来说还是太多了
      • 好了,现在如何检查口是心非。。。

        List<WORD> src;  // src is input list
        BYTE cnt[65536]; // count usage for all used numbers
        int i;
        for (i=0;i<65536;i++) cnt[i]=0; // clear the count for all numbers
        for (i=0;i<src.num;i++)         // compute the count for used numbers in the list  
         if (cnt[src[i]]!=255) 
          cnt[src[i]]++;
        
      • 在此之后,如果(cnt[i]>1),则任何数字i都是重复的
      • 所以现在我们要删除重复的项目(除一个项目外的所有项目)
      • 这样改变cnt[]

        for (i=0;i<65536;i++) if (cnt[i]>1) cnt[i]=1; else cnt[i]=0;
        
      • 好了,现在是删除部分:

        for (i=0;i<src.num;i++)         
         if (cnt[src[i]]==1) cnt[src[i]]=2; // do not delete the first time
          else if (cnt[src[i]]==2)          // but all the others yes
           { 
           src.del(i);
           i--;                             // indexes in src changed after delete so recheck for the same index again
           }
        
    3. 你可以把这两种方法结合起来

    4. 由于列表中的项目移位,从列表中删除项目的速度很慢
      • 但可以通过在项目中添加删除标志来加快速度
      • 不删除,只设置标志
      • 并且在标记了所有要删除的项目之后,然后立即简单地移除下摆O(n)

    PS.很抱歉使用非标准列表,但如果不评论我,我认为代码是可以理解的,我会回应

    PPS。要与带符号的值一起使用,请不要忘记将地址移动一半范围!!!

        10
  •  0
  •   Dharmendra Pratap Singh    9 年前

    下面我给出了一个示例,它实现了一个通用函数来从arraylist中删除重复项,同时维护顺序。

    import java.util.*;
    public class Main {
        //Generic function to remove duplicates in list and maintain order
        private static <E> List<E> removeDuplicate(List<E> list) {
            Set<E> array = new LinkedHashSet<E>();
            array.addAll(list);
            return new ArrayList<>(array);
        }
        public static void main(String[] args) {
            //Print [2, 3, 5, 4]
            System.out.println(removeDuplicate(Arrays.asList(2,2,3,5, 3, 4)));
            //Print [AB, BC, CD]
            System.out.println(removeDuplicate(Arrays.asList("AB","BC","CD","AB")));
        }
    }
    
        11
  •  0
  •   Soudipta Dutta    8 年前

    方法1:在Python中=>使用集合和列表理解

    a= [139, 127, 127, 139, 130]
    
    print(a)
    seen =set()
    aa = [ch  for ch in a if ch not in seen and not seen.add(ch)]
    print(aa)
    

    方法2:

    aa = list(set(a))
    print(aa)
    

    在Java中:使用Set并创建新的ArrayList

    class t1 {
        public static void main(String[] args) {
    
    int[] a = {139, 127, 127, 139, 130};
    List<Integer> list1 = new ArrayList<>();
    
    Set<Integer> set = new LinkedHashSet<Integer>();
    for( int ch  : a) {
        if(!set.contains(ch)) {
            set.add(ch);
        }
    
    
    }//for
    set.forEach( (k) -> list1.add(k));
    System.out.println(list1);
    
    }
        }
    
        12
  •  0
  •   Abhishek    4 年前
    Bro this is you answer but this have 0(n2) T.C remember.
    
    vector<int> sol(int arr[],int n){
    vector<int> dummy;
    for(int i=0;i<n-1;i++){
    for(int j=i+1;j<n;j++){
        if(arr[i]==arr[j]){
            dummy.push_back(j);
        }
       }
     }
     vector<int> ans;
     for(int i=0;i<n;i++){
     bool check=true;
      for(int j=0;j<dummy.size();j++){
        if(dummy[j]==i){
            check=false;
        }
     }
     if(check==false)
       continue;
      ans.push_back(arr[i]);
      }
      return ans;
      }