【问题标题】:Finding index of duplicated element in arraylist在arraylist中查找重复元素的索引
【发布时间】:2021-03-15 02:02:25
【问题描述】:

我正在尝试在字符串数组列表中查找重复项的索引位置。我无法找到一种有效循环遍历数组列表并报告重复索引的方法。我最初的想法是使用 Collections.binarySearch() 来查找重复项,但我不确定如何使用 binarySearch 将数组列表的元素相互比较。我唯一的另一个想法是遍历列表,这非常庞大,次数太多甚至都不可行。我的 Java 知识有限,因此不胜感激。

【问题讨论】:

  • binarySearch 仅适用于排序列表。
  • 有限的 Java 知识无济于事。
  • 对,我知道。问题是我不知道如何使用 binarysearch 搜索重复项,因为我的初始搜索值将在 arraylist 中,所以它不会总是返回该索引吗?
  • 你知道重复元素是什么吗?或者您正在搜索列表中的任何重复项?
  • 如果您使用Collections.sort(yourList); 对列表进行排序,则重复项将彼此相邻,但我想这不适用于您的用例,是吗?

标签: java arraylist binary-search


【解决方案1】:

不优雅,但应该可以:

Map<String, List<Integer>> indexList = new HashMap<String, List<Integer>>();
for (int i = 0; i < yourList.size(); i++) {
    String currentString = yourList.get(i);
    List<String> indexes = indexList.get(currentString);
    if (indexes == null) {
         indexList.put(currentString, indexes = new LinkedList<Integer>());
    }
    indexes.add(i);
    if (indexes.size() > 1) {
        // found duplicate, do what you like
    }
}
// if you skip the last if in the for loop you can do this:
for (String string : indexList.keySet()) {
    if (indexList.get(string).size() > 1) {
        // String string has multiple occurences
        // List of corresponding indexes:
        List<Integer> indexes = indexList.get(string);
        // do what you want
    }
}

【讨论】:

  • 我正是想到了这一点,然后我看了你的回答,你和我想到的完全一样。 :) 这很好,因为它只会在 ArrayList 上迭代一次,并且除了简单的空检查之外不进行任何迭代比较。 PS:我认为您的意思是 indexList.put 在第 6 行。
  • @ADTC 是的,它还会发现一个字符串是否出现超过 2 次。感谢您的提示,更新了我的答案。
  • “它还会发现一个字符串是否出现超过 2 次” 这当然是要问的 :)
  • 是的,当我听到重复时,我总是会想到正好 2。但是现在,在考虑之后,我找不到另一个词来表示多次出现 ;)
  • 通常当一个人说“重复”时,意思是多次出现(两个或更多)。但是,是的,歧义是存在的——这对你来说是通用语言:)
【解决方案2】:

听起来你运气不好。

您将必须检查每个元素(即遍历整个列表)。从逻辑上考虑 - 如果你能避免这种情况,这意味着你没有检查过一个元素。但是这个元素可以是任何值,因此可以是另一个列表元素的副本。

当您知道列表中存在某种关系时,二分搜索是一种减少检查元素数量的明智方法,因此检查一个元素可以为您提供有关其他元素的信息。例如,对于一个排序列表,如果中间元素大于 5,则您知道它后面的每个元素也都大于 5。

但是,我认为在重复检查方面没有办法做出这样的推断。您必须根据“此重复的元素数量”(这是在回避问题)对列表进行排序,否则您对元素 x 执行的任何测试都不会让您深入了解 y 是否重复。

【讨论】:

    【解决方案3】:

    现在这可能不是一个内存效率高的解决方案,但我想这就是您要寻找的......也许这个程序可以进一步改进。

    import java.io.*;
    import java.util.*;
    
    class ArrayList2_CountingDuplicates
    {
    public static void main(String[] args)throws IOException
    {
    
    ArrayList<String> als1=new ArrayList<String>();
    ArrayList<String> als2=new ArrayList<String>();
    int arr[];
    int n,i,j,c=0;
    String s;
    
    BufferedReader p=new BufferedReader(new InputStreamReader(System.in));
    
    n=Integer.parseInt(p.readLine());
    
    arr=new int[n];
    
    for(i=0;i<n;i++)
    als1.add(p.readLine());
    
    for(i=0;i<n;i++)
    {
    
    s=als1.get(i);
    als1.remove(i);
    als2.add(s);
    
    arr[c]=1;
    
    while(als1.contains(s))
    {
    j=als1.indexOf(s);
    als1.remove(j);
    arr[c]=arr[c]+1;
    }
    n=n-arr[c];
    c=c+1;
    i=-1;
    }
    
        for(i=0;i<c;i++)
        System.out.println(als2.get(i)+" has frequency  "+arr[i]);
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      我一直在寻找这样的方法,最终我想出了自己的解决方案,并采用更实用的方法来解决问题。

      public <T> Map<T, List<Integer>> findDuplicatesWithIndexes(List<T> elems) {
          return IntStream.range(0, elems.size())
                  .boxed()
                  .collect(Collectors.groupingBy(elems::get))
                  .entrySet().stream()
                  .filter(e -> e.getValue().size() > 1)
                  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
      }
      

      它返回一个由重复元素作为键和重复元素的所有索引作为值的列表组成的映射。

      【讨论】:

        猜你喜欢
        • 2022-01-18
        • 2019-12-31
        • 1970-01-01
        • 2016-10-05
        • 2017-04-15
        • 2016-12-29
        • 1970-01-01
        • 2021-08-23
        相关资源
        最近更新 更多