【问题标题】:Java: how to count non-repeated (occurring only once) Strings in ArrayList?Java:如何计算 ArrayList 中不重复(仅出现一次)的字符串?
【发布时间】:2016-03-14 19:13:25
【问题描述】:

我正在尝试查找在 ArrayList 中仅出现一次的字符串数。

我实现了多少(最好具有最佳的时间复杂度)?

下面是我的方法:

  public static int countNonRepeats(WordStream words) {

    ArrayList<String> list = new ArrayList<String>();
    for (String i : words) {
      list.add(i);
    }

    Collections.sort(list);

    for (int i = 1; i < list.size(); i++) {
      if (list.get(i).equals(list.get(i - 1))) {
        list.remove(list.get(i));
        list.remove(list.get(i - 1));
      }
    }

    System.out.println(list);

    return list.size();
  }

为什么不删除list.get(i)list.get(i-1) 的字符串?

【问题讨论】:

  • @FedericoPeraltaSchaffner 你有什么想法吗? :)
  • 上述方法会出现并发修改异常。
  • @RahulSharma 不完全是,迭代器抛出并发修改异常,它主要是通过 for-each 创建的,而不是简单的 for(i..)。但是我们可能会因为错误的索引而冒着出错的风险。
  • 抱歉,没有。但我试图运行代码,它就像一个魅力。 @Iona 你有什么错误吗?
  • 如果使用Collections.sort,则时间复杂度为O(n log n),但使用HashSets(但不排序)可以轻松找到在O(n)时间中恰好出现一次的字符串数.

标签: java string arraylist unique non-repetitive


【解决方案1】:

不需要排序。 更好的方法是使用两个 HashSet 一个来维护重复单词,一个用于非重复单词。由于 HashSet 内部使用 HashMap,理想情况下 contains、get、put 操作的复杂度为 o(1)。所以这种方法的整体复杂度是 o(n)。

    public static int countNonRepeats(List<String> words) {

    Set<String> nonRepeating = new HashSet<String>();
    Set<String> repeating = new HashSet<String>();


    for (String i : words) {
        if(!repeating.contains(i)) {
            if(nonRepeating.contains(i)){
                repeating.add(i);
                nonRepeating.remove(i);
            }else {
                nonRepeating.add(i);
            }
        }
    }

    System.out.println(nonRepeating.size());

    return nonRepeating.size();
}

【讨论】:

    【解决方案2】:

    这里有一个简单的建议:

    1. 首先,按字母数字顺序对数组进行排序
    2. 循环遍历,if( !list.get(i).equals(list.get(i+1)) ) → unique
    3. 如果发现重复项,请递增 i 直到找到不同的字符串

    这会有排序算法的复杂度,因为第2+3步应该是O(n)

    【讨论】:

    • 那行不通,因为例如[apple,apple,banana,banana] 将返回 1 而不是 0 因为 apple !=banana
    • 不,因为这是第 3 步避免的!仔细阅读。在此示例中,"apple"i = 0 重复,因此您迭代直到 !list.get(i).equals("apple")i = 2 在下一个循环中
    • 好吧,你是对的!谢谢你,先生! :) 我会在 10 秒内投票
    • @Iona 我实现了多少(最好具有最佳的时间复杂度) 实际上,您甚至不必再次迭代它。如果您使用的是HashSet,那么您可以在扫描单词的同时进行。
    • 不需要排序,请看我的答案以获得更好的时间复杂度。
    【解决方案3】:

    是否有任何特殊需要使用ArrayList?您可以使用HashSet 轻松完成。

    这里是sn-p的代码:

    public static void main (String[] args) {
        String[] words = {"foo","bar","foo","fo","of","bar","of","ba","of","ab"};
        Set<String> set = new HashSet<>();
        Set<String> common = new HashSet<>();
        for (String i : words) {
            if(!set.add(i)) {
                common.add(i);
            }
        }
    
        System.out.println(set.size() - common.size());
    }
    

    输出:

    3
    

    这是修改后的代码:

    public static int countNonRepeats(WordStream words) {
        Set<String> set = new HashSet<>();
        Set<String> common = new HashSet<>();
        for (String i : words) {
            if(!set.add(i)) {
                common.add(i);
            }
        }
    
        return (set.size() - common.size());
    }
    

    【讨论】:

    • 你打败了我!您可以通过 if (!set.add(i)) common.add(i); 使其效率更高一些
    • @PaulBoddington 明白了! :) 感谢您的宝贵建议。
    【解决方案4】:

    您可以使用 hashmap 来实现这一点。通过这种方法,我们可以计算所有单词的出现次数,
    如果我们只对唯一单词感兴趣,则访问 count = 1 的元素。
    HashMap&lt;String,Integer&gt; - key 表示来自 arraylist 的 String,Integer 表示出现次数。

            ArrayList<String> list = new ArrayList<String>();
            HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
    
            for (int i = 0; i < list.size(); i++) {
    
                String key = list.get(i);
    
                if (hashMap.get(key) != null) {
                    int value = hashMap.get(key);
                    value++;
                    hashMap.put(key, value);
                } else {
                        hashMap.put(key, 1);
                }
    
            }
            int uniqueCount = 0;
            Iterator it = hashMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry pair = (Map.Entry) it.next();
                if ((int) pair.getValue() == 1)
                    uniqueCount++;
            }
            System.out.println(uniqueCount);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 2012-05-31
      • 2011-03-02
      • 2021-07-06
      • 2013-11-04
      相关资源
      最近更新 更多