【问题标题】:How to find out the most appear numbers from the String?如何从字符串中找出出现次数最多的数字?
【发布时间】:2012-02-14 04:53:44
【问题描述】:

我有一个String,其中包含以逗号分隔的数字。我想从字符串中提取出现次数最多的数字。 例如,我有一个类似..的字符串。

String str="1,2,3,4,5,6,7,19,18,4";

从上面的 str 我需要 4,因为 4 是 str 的两倍。

String str2="1,2,3,4,6,4,3,9";

从上面的 str2 我需要 3,4

如果所有数字都是唯一的,那么我需要第一个。

建议我更好的方法。

【问题讨论】:

  • 这需要一些时间才能找出数字,因为 str 有很多数字。
  • 首先,我不会使用字符串,因为将其转换为数字可能需要比搜索更长的时间。

标签: java string frequency


【解决方案1】:

这是使用java.utilGuava collect 的解决方案。

大纲:

  1. 将字符串拆分为单词列表
  2. 统计每个词出现的频率并创建地图Word -> Count
  3. 反转以创建多图Count -> Words
  4. 转换为排序的 NavigableMap
  5. 获取计数最高的单词
  6. 返回计数最高的单词

代码:

public class HighestCountFinder {


    public static ImmutableSet<String> findWordsWithGreatestCount(String wordsString) {
        List<String> words = split(wordsString, ",");

        Map<String, Integer> wordsToCounts = toMapWithCounts(words);

        Multimap<Integer, String> countsToWords = toInverseMultimap(wordsToCounts);

        NavigableMap<Integer, Collection<String>> countsToWordsSorted = toNavigableMap(countsToWords);

        Collection<String> wordsWithHighestCount = lastValue(countsToWordsSorted);

        return ImmutableSet.copyOf(wordsWithHighestCount);
    }


    public static ImmutableList<String> split(String wordsString, String separator) {
        Iterable<String> parts = Splitter.on(separator).split(wordsString);
        return ImmutableList.copyOf(parts);
    }


    public static ImmutableMap<String, Integer> toMapWithCounts(Iterable<String> entries) {
        Multiset<String> entriesWithCounts = HashMultiset.create(entries);
        return toMap(entriesWithCounts);
    }


    public static <E> ImmutableMap<E, Integer> toMap(Multiset<E> multiset) {
        ImmutableMap.Builder<E, Integer> immutableMapBuilder = ImmutableMap.builder();
        for (Multiset.Entry<E> entry : multiset.entrySet()) {
            immutableMapBuilder.put(entry.getElement(), entry.getCount());
        }
        return immutableMapBuilder.build();
    }


    public static <K, V> ImmutableMultimap<V, K> toInverseMultimap(Map<K, V> map) {
        Multimap<K, V> multimap = Multimaps.forMap(map);
        return ImmutableMultimap.copyOf(multimap).inverse();
    }


    public static <K, V> NavigableMap<K, Collection<V>> toNavigableMap(Multimap<K, V> multimap) {
        return new TreeMap<>(multimap.asMap());
    }


    public static <V> V lastValue(NavigableMap<?, V> navigableMap) {
        return navigableMap.lastEntry().getValue();
    }
}

【讨论】:

    【解决方案2】:

    我会有一个整数映射数组来计算每个数字,并有一个变量来存储计数最高的数字。

    将字符串拆分成一个数字列表,然后循环遍历列表。

    每次查看新数字时,在地图中增加其计数器,如果该计数大于当前最高计数,则将当前最高更改为当前。在字符串的末尾,返回当前最高值。

    请注意,如果您还存储具有第二大计数的数字,您可以通过提前退出循环来稍微优化,此时没有足够的数字让第二高的计数超过最高计数。

    【讨论】:

      【解决方案3】:

      试试下面的代码

      public class StringCheck {
          public static void main(String args[]) {
              String input = "1,2,3,4,5,6,2,3,4,1,4,33,33,33";
              String result = "";
              String[] arr1 = input.split(",");
      
              System.out.println("Input is : " + input);
      
              for (int i = 0; i < arr1.length; i++) {
                  int k = 0;
                  for (int j = 0; j < arr1.length; j++) {
                      if (arr1[i].equals(arr1[j])) {
                          k++;
                          if (k == 2) {
                              if (result.contains(arr1[i])) {
                                  break;
                              }
                              result = result + arr1[i] + ",";
                              break;
                          }
                      }
                  }
              }
      
              System.out.println("Result is " + result);
          }
      }    
      

      下面会输出

      Input is : 1,2,3,4,5,6,2,3,4,1,4,33,33,33
      Result is 1,2,3,4,33,
      

      如果有任何疑问,请告诉我...

      干杯!!!

      【讨论】:

        【解决方案4】:

        将您的字符串转换为数字列表。

        记住列表的第一个数字是什么。

        对数字列表进行排序。

        遍历列表并保持

        • 当前数字的出现次数。
        • 数字的当前最大出现次数
        • 你遇到的不同数字的数量
        • 出现次数等于最大值的一组数字

        在每次迭代中,如果当前数等于当前最大值,则将当前数添加到结果中。如果大于当前最大值,则清除结果集并将当前数字添加到结果中。

        在循环结束时,如果结果集的大小等于不同数字的数量,则在对列表进行排序之前返回您记住的第一个数字。

        【讨论】:

          【解决方案5】:

          假设这是一个家庭作业,我将提出一个没有代码的总体思路:

          • 首先在',' 字符上拆分字符串
          • 使用计数创建一个初始为空的从 IntegerInteger 的映射
          • 检查从拆分中返回的部分,并将它们解析为 int
          • 对于每一个值,看map中是否有对应的item;如果那里有数字,请增加它;否则,使用新号码和1 添加一个条目。
          • 完成令牌后,请浏览地图并找到最大值
          • 如果最大值为1,则返回第一个令牌
          • 如果max不是1,再遍历map,收集所有值等于max的key

          这种方法可以让您处理非常大的数字,并且它不区分带前导零和不带前导零的数字。换句话说,它将1,2,03,3,3,2序列中的3识别为唯一的赢家,而不是与2平分秋色。

          【讨论】:

            【解决方案6】:

            您可以使用java.util.StringTokenizer 标记字符串,使用, 作为分隔符,然后使用String.trim() 去除每个标记的前导和尾随空格,然后使用@987654325 将它们存储到ints 数组中@ 功能。然后你就可以轻松数数了。

            计数:

            如果您的数字范围很小,那么您可以简单地创建一个计数器数组并将每个数字用作该数组的索引。如果没有,那么你可以使用HashMap 或类似的东西。

            【讨论】:

            • 个人建议使用java.util.Scanner"\\s*,\\s*"作为分隔符,使用nextInt方法检索整数。
            猜你喜欢
            • 2021-03-19
            • 1970-01-01
            • 2015-03-25
            • 1970-01-01
            • 2014-03-28
            • 2015-01-10
            • 2011-04-03
            相关资源
            最近更新 更多