【问题标题】:Finding the most Repetitive number using Divide and Conquer approach?使用分而治之的方法找到最重复的数字?
【发布时间】:2018-11-09 16:09:23
【问题描述】:

我有一个整数数组列表 5, 12, 5, 17, 5, 5, 5, 39 我试图找到 重复次数最多的 数将打印5的作品。

但是,我想使用分而治之的方法来编写它。

任何提示都会有所帮助(伪代码、Java 代码或任何帮助...)

public static void main(String[] args) {

        int[] repetitive = { 5, 12, 5, 17, 5, 5, 5, 39 };
        int counter = 1;
        int temp = 0;
        int checker = 1;

        Arrays.sort(repetitive);
        int cont = repetitive[0];

        for (int i = 1; i < repetitive.length; i++) {
            if (repetative[i] == repetitive[i - 1] && cont == repetitive[i]) {
                counter++;
                temp = repetitive[i];

            } else if (repetitive[i] == repetitive[i - 1]) {
                checker++;

                if (checker > counter) {
                    temp = repetitive[i];
                } else if (repetitive[i] != repetitive[i - 1]) {
                    checker = 1;
                }
            }
        }

        System.out.println(temp);
    }

【问题讨论】:

  • 你的意思是要找模式吗?
  • 在您的示例中,5 和 12 都出现了 3 次。为清楚起见,您可能应该确保示例中只有一个“重复次数最多”的数字。
  • 感谢@JimMischel 的警告,我已修复。
  • @johntame 您所描述的是模式,即“最常出现的值”。 en.wikipedia.org/wiki/Mode_(statistics)
  • 对于建议使用地图的每个人,这不是 OP 所要求的。他在问如何使用分而治之的方式来做到这一点。你们都缺少的一点是,如果Arrays.sort() 使用快速排序(一种分而治之的算法),那么他已经解决了他的问题。 OP 可以说他想在不使用任何显式额外内存的情况下解决问题,例如地图所需的 O(n) 内存。那会澄清很多事情。

标签: java algorithm dynamic-programming divide-and-conquer


【解决方案1】:

为什么要在示例代码中对其进行排序?那时,您可以从头开始遍历它,找到重复次数最多的。

假设您在分而治之之前对其进行排序,那么您应该计算列表的大小,找到中间点。通常,分/治是用于合并排序之类的东西,并且您使用递归。在这种情况下,您正在尝试使用它来计算每个值 - 它似乎不是最合适的,因为您需要在执行递归时以某种方式保持具有最高计数的状态(这意味着传递一些东西)。

这里的动机究竟是什么,而不是仅仅遍历数组并在地图或其他东西中保持计数。那将是 O(n) 时间和 O(n) 空间。

【讨论】:

    【解决方案2】:

    分而治之不是一种适合在这里应用的技术,因为不能保证从整个列表的任何 2 个细分中得出相同的结果。即使您对列表进行排序也不会,因为您可能会在子列表之间拆分最大的组,此时您会在每个子列表中找到不同的最大组并完全错过正确的结果。

    正如thejavagirl 所建议的,枚举列表并计算出现次数绝对是最简单和最好的方法。

    【讨论】:

      【解决方案3】:

      此代码计算数组中给定数字的出现次数(效率不高,但这应该可以帮助您入门)

      public static void main(String[] args) {
          int[] repetitive = { 5, 12, 5, 17, 12, 12, 5, 39 };
          System.out.println(countOccurences(repetitive));
      }
      
      public static Map<Integer, Integer> countOccurences(int[] arr) {
          if (arr.length == 1) {
              Map<Integer, Integer> result = new HashMap<>();
              result.put(arr[0], 1);
              return result;
          } else {
      
              int to = arr.length / 2;
              Arrays.copyOfRange(arr, 0, to);
      
              Map<Integer, Integer> left = countOccurences(Arrays.copyOfRange(arr, 0, to));
              Map<Integer, Integer> right = countOccurences(Arrays.copyOfRange(arr, to, arr.length));
              return merge(left, right);
          }
      }
      
      static Map<Integer, Integer> merge(Map<Integer, Integer> left, Map<Integer, Integer> right) {
          right.forEach((number, count) -> {
              left.compute(number, (num, c) -> c == null ? count : c + count);
          });
          return left;
      }
      

      【讨论】:

      • @JimMischel(高效)响应已修复
      【解决方案4】:

      您可以调整快速排序以比先排序数组然后找到最长序列更有效地执行此操作(*)。思路如下:

      在快速排序中,您通常选择一个元素 x,并将元素 &lt;x 放在左侧,将其他元素放在右侧 - 然后递归地对左右数组进行排序。

      在这里你将元素三等分:左&lt;x,右&gt;x,只计算等于x的元素数量,然后你就可以处理左右数组了。

      这本身并没有任何好处,但可以优化以跳过对元素不超过当前重复数字的任何数组进行排序 - 如果你有更多内存,你可以维护剩余数组的优先级队列 -始终首先考虑具有最多元素的数组,并且一旦所有数组的元素不超过当前最经常出现的元素,您就完成了。

      *:注意:只有在实际存在高度重复的数字时才会更有效率。

      【讨论】:

        【解决方案5】:

        你想做什么是没有意义的......

        我认为“分而治之”是“二进制搜索”的隐喻,用于 [顾名思义] 搜索,用它来计数是没有意义的。

        如果您想获得更好的性能方法,您有几个不需要排序的选项。

        1. 如果内存不是限制并且您知道最大数量 可能出现在您的列表中,创建一个数组并在每个索引处 计算该索引的准确次数
        2. 如果你有记忆 限制、负数或您不知道最大值 可能的值,使用 Map 来使用相同的方法。在 每个键你计算该值的重复次数

        【讨论】:

        • 这个答案是错误的。首先,分而治之不仅仅是二分搜索。您的第一个建议做出了不切实际的假设,即内存不是问题,而您的第二个“节省内存”建议忽略了 Map 可能对内存来说太大的可能性。
        • @JimMischel,请算法和疯狂结构中的博士先生回答最初的问题......我会很高兴标记它......如果你能做到这一点并且使用比地图更少的内存跨度>
        • OP 已经展示了如何使用比地图更少的内存来做到这一点:排序和计数。
        • 我的方法是 O(n) 他是 O(nlogn)... 再加上它不是“分而治之”,最后你证明你自己无法提供满足你的答案自己的要求...干得好胖子
        • 我不是 OP。 OP的问题无法回答,因为没有分而治之的解决方案。由于我指出的原因,有一个不使用分而治之的更省时的解决方案是无关紧要的,并且不会改变我认为你的答案是错误的观点。仅您关于分而治之的断言就足以引起反对。但是,嘿,我的鼻子上没有皮肤。如果你想继续宣传你的无知,即使在有机会纠正它之后,你也有更多的权力。 en.wikipedia.org/wiki/Divide_and_conquer_algorithm
        猜你喜欢
        • 2016-06-15
        • 1970-01-01
        • 2023-03-14
        • 2015-12-31
        • 2017-01-25
        • 2021-08-21
        • 2016-12-08
        • 2017-03-23
        • 2017-01-12
        相关资源
        最近更新 更多