使用Divide and Conquer方法找到最重复的数字?

时间:2018-05-30 17:57:57

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

我有一个整数arrayList,它是 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 个答案:

答案 0 :(得分:0)

为什么要在示例代码中对其进行排序?那时,您可以从头开始查看最重复的内容。

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

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

答案 1 :(得分:0)

划分和征服不适合在此处应用,因为无法保证从整个列表的任何2个细分中获得相同的结果。即使您对列表进行排序也不会,因为您可以在子列表之间拆分最大的组,此时您将在每个子列表中找到不同的最大组,并完全错过正确的结果。

正如thejavagirl所建议的那样,枚举列表和计算事件绝对是最简单和最好的方法。

答案 2 :(得分:0)

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

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;
}

答案 3 :(得分:0)

你可以采用快速排序来比第一次排序数组然后找到最长的序列更有效地执行此操作(*)。这个想法如下:

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

这里你要点三个元素:左<x,右>x,只计算等于x的元素数,然后你就可以处理左右数组了。

本身并没有获得任何东西,但可以优化以跳过排序任何没有比当前最重复数字更多元素的数组 - 如果你有更多内存,你可以维护剩余数组的优先级队列 - 要始终首先考虑具有大多数元素的数组,并且只要所有数组都没有比当前最重复的元素更多的元素。

*:注意:如果实际上有高度重复的数字,它只会更有效。

答案 4 :(得分:-2)

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

&#34;划分和征服&#34;我认为这是对二元搜索的一个比喻&#34;用于[如名称所述]搜索它没有意义用它计算。

如果您想获得更好的性能方法,您可以选择几种不需要排序的选项。

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