【问题标题】:find duplicates in a sorted linkedlist in O(n) time在 O(n) 时间内在已排序的链表中查找重复项
【发布时间】:2013-11-10 20:45:20
【问题描述】:

最初,我使用了时间复杂度为 0(n^2) 的嵌套循环。为了更有效的 0(n),解决方案我编写了以下代码,并希望获得一些帮助/了解如何找出任何元素及其 .Next() 是否具有相同的值“重复”,如果是,请打印他们出去。

public class FindDuplicates {
    public static void main(String arg[]){
        int[] str={1 , 2 , 3 ,4  ,5 ,3 ,5 , 4,3,43,1,33,4,5};
        List<Integer> list = new LinkedList<Integer>();

        for(int x : str) {   
            list.add(x);    
        }

        Collections.sort(list);
        System.out.println(list);

        Iterator<Integer> it = list.listIterator();  
        while(it.hasNext() && it.next() != null) { 
            /*   Pseudocode =>   if(it.next().equals(it.next.next)); */
            /* OR Pseudocode =>  if(it.next() == it.next().next) */ 
            System.out.println(it) ;
        }
    }
}

【问题讨论】:

  • 那么问题是什么?你想让你的代码被审查还是什么?
  • 尝试定义一个名为int lastEntry的变量。如果 lastEntry != currentEntry 则打印 currentEntry。这仅适用于排序列表。
  • 在担心性能的情况下,您能说出为什么要使用LinkedList 吗?它内存效率低(每个列表项大约 8-16 个字节)、缓存效率低(堆上的数据)和算法受限(随机访问是 O(n)),并且仅有用用于一些非常特殊的用途。
  • @StackUnderFlow 您的方法很好,但您的解决方案取决于collections.sort(),它的时间复杂度为nlog(n)。检查我的答案,它会给你O(n) 时间复杂度。
  • @Prateek 您的 collections.sort() 确实如此,但此操作只会执行一次(对列表进行一次排序)。就时间复杂度而言,这仍然是可行的解决方案。“更好的坏选择”

标签: java arrays list linked-list


【解决方案1】:

你需要将之前的值保存在一个变量中,看起来应该是这样的:

 Iterator<Integer> it = list.listIterator(); 
 if (it.hasNext()) {
   Integer previous = it.next();
   while(it.hasNext()) { 
     Integer current = it.next();
     if (previous.equals(current)) {
       System.out.println("Dupe: " + current);
     }
     previous = current;
   }
 }

请注意,您实际上并不需要链表(正如其他人已经指出的那样),您可以就地排序,然后使用单个循环扫描数组:

int[] str={1 , 2 , 3 ,4  ,5 ,3 ,5 , 4,3,43,1,33,4,5};
Arrays.sort(str);
for (int i = 1; i < str.length; i++) {
  if (str[i] == str[i - 1]) {
    System.out.println("Dupe: " + str[i];
  }
}

如果您不想更改 str,只需跟踪 HashSet 中的元素即可:

int[] str={1 , 2 , 3 ,4  ,5 ,3 ,5 , 4,3,43,1,33,4,5};
HashSet<Integer> seen = new HashSet<Integer>();
for (int i: str) {
  if (seen.contains(i)) {
    System.out.println("Dupe: " + i);
  } else {
    seen.add(i);
  }
}

如果你考虑哈希表操作 O(1),这也会给你线性时间而不是 O(n log n)

【讨论】:

  • 谢谢,这是有道理的。
  • 以下是我如何使用 0(n^2) 时间复杂度 ArrayList list = new ArrayList(Arrays.aslist(str)); for(String x : list){ int count=0; for(String y : list){ if(x.equals(y)) count ++; } if(count %2 !=0){ System.out.println(x); } } }
  • 您编写的第一个代码完美地完成了这项工作,刚刚试了一下。 Hashset 解决方案也“非常直观”。感谢您的宝贵时间。
  • 输出 [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 33, 43] 复制:1 复制:3 复制:3 复制:4欺骗:4 欺骗:5 欺骗:5
  • 刚刚做了,谢谢。不知道这个功能。
【解决方案2】:

首先,请注意您使用的是Collections.sort,它的复杂度高于 O(n)。

关于您的问题:在复杂度为 O(n) 的 排序列表 中查找重复项:

您可以只将一个变量设置为之前遇到的值,这样在循环中,您只需将当前值与该变量进行比较,然后将变量设置为当前值。

【讨论】:

    【解决方案3】:

    更好的方法是 .除非您对space complexity 有限制,否则请使用Hash Set,而不是高于O(N) 复杂性的Collections.sort。一个基本的伪代码是这样的。

      if(set.contains(it)){// Check if it.info is in map or not
        System.out.println(it.info); // If it was then it is duplicate element hence print it
        }
      else{
        set.put(it);// Else if this is the first time you saw this element put it in set.
        }
    

    这段代码的时间复杂度为O(N)。

    【讨论】:

    • 我明白你现在的意思了。谢谢
    【解决方案4】:
    int[] str={1 , 2 , 3 ,4  ,5 ,3 ,5 , 4,3,43,1,33,4,5};
    

    您不需要使用LinkedList 来排序以查找重复项。使用Arrays.sort(int[]) 对数组进行排序然后扫描:以下程序将打印具有重复项的整数以及重复项计数:

    int a[] = {1, 1, 1, 5, 5, 4, 4, 3, 3};
    
            Arrays.sort(a);
    
            for(int i=1 ; i<a.length;)
            {
                if(a[i] == a[i-1])
                {
                    int j = i;
                    for(; j<a.length; j++)
                        if(a[j]!=a[i])break;
    
                    if(j > i)
                        System.out.println("Found duplicate: "+a[i]+" counted: "+(j - i+1));
    
                    i = j;
                }
                else i++;
    
            }
    

    样本输出:

    Found duplicate: 1 counted: 3
    Found duplicate: 3 counted: 2
    Found duplicate: 4 counted: 2
    Found duplicate: 5 counted: 2
    

    【讨论】:

      【解决方案5】:

      所有带数组、带列表、带链表的表单。

      import java.util.Arrays;
      import java.util.Collections;
      import java.util.Iterator;
      import java.util.LinkedList;
      import java.util.List;
      
      public class Main {
      
          public static void withArray() {
              int[] str = { 1, 2, 3, 4, 5, 3, 5, 4, 3, 43, 1, 33, 4, 5 };
              Arrays.sort(str);
      
              int previous = str[0];
              for (int i = 1; i < str.length; ++i) {
                  if (str[i] == previous) {
                      System.out.println("Duplicate " + previous + " and " + str[i]);
                  }
                  previous = str[i];
              }
              System.out.println();
          }
      
          public static void withList() {
              List<Integer> str = Arrays.asList(1, 2, 3, 4, 5, 3, 5, 4, 3, 43, 1, 33,
                      4, 5);
              Collections.sort(str);
      
              int previous = str.get(0);
              for (int i = 1; i < str.size(); ++i) {
                  if (str.get(i) == previous) {
                      System.out.println("Duplicate " + previous + " and "
                              + str.get(i));
                  }
                  previous = str.get(i);
              }
              System.out.println();
          }
      
          public static void withLinkedList() {
              LinkedList<Integer> str = new LinkedList<Integer>(Arrays.asList(1, 2,
                      3, 4, 5, 3, 5, 4, 3, 43, 1, 33, 4, 5));
              Collections.sort(str);
      
              Iterator<Integer> it = str.iterator();
      
              int previous = it.next();
              int cur;
              while (it.hasNext()) {
                  cur = it.next();
                  if (cur == previous) {
                      System.out.println("Duplicate " + previous + " and " + cur);
                  }
                  previous = cur;
              }
              System.out.println();
          }
      
          public static void main(String arg[]) {
              withArray();
              withList();
              withLinkedList();
      
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-28
        • 2011-08-09
        • 2013-11-01
        • 1970-01-01
        • 2017-01-26
        • 2011-05-08
        • 1970-01-01
        • 2023-01-16
        • 2019-11-19
        相关资源
        最近更新 更多