Divided和Conquer算法如何与给定的输入一起工作?

时间:2013-04-07 05:43:17

标签: recursion input divide

我在java中编写了一个分而治之的算法。 问题是,我已经测试了它的工作原理,除了我不确定为什么或它对数据有什么作用。我知道它将数组拆分成子部分,但除此之外,我很困惑他们将所有东西都归还了什么。 例如,最小的基本案例是否返回其数字并进行比较?如果函数中有多个递归调用,那么递归的顺序是什么? 我的代码是:

public static int FindMin(int[] array, int low, int high)
{
int min = 0, min1 = 0, min2 = 0;
int mid = 0;
if (low == high)
    {
    min = array[low];
    }
else if (low == (high - 1))
    {
    if (array[low] < array[high])
        {
        min = array[low];
        }
    else if (array[low] > array[high]);
        {
        min = array[high];
        }
    }
else
    {
    mid = (low + high)/2;
    min1 = FindMin(array, low, mid);
    min2 = FindMin(array, mid+1, high);
    if (min1 < min2)
        {
        min = min1;
        }
    else
        {
        min = min2;
        }
    }
return min;
}

基本上我想知道的是: 如果给出输入,算法将如何工作:3,6,1,5,7,2,1。 就像它返回的东西一样。

我很抱歉,如果这个问题有点含糊不清,但我知道如何编码,我似乎无法理解它是如何返回所有内容的,无论我开始使用的所有谷歌页面和PDF格式。

感谢所有的帮助! :d

2 个答案:

答案 0 :(得分:1)

虽然调试器很有用,但有时正确的日志文件输出可以提供更多的洞察力。我在FindMin()函数末尾添加了对以下函数的调用,就在return min;语句之前:

public static void pr (int[] array, int low, int high, int min) {
    System.out.print("low = ");
    System.out.print(low);
    System.out.print(", high = ");
    System.out.print(high);
    System.out.print(", array = ");
    for (int i = low; i <= high; i++) {
        System.out.print(array[i]);
        if (i < high) {
            System.out.print(",");
        }
    }
    System.out.print(" min = ");
    System.out.print(min);
    System.out.print("\n");
}

我得到的输出是:

low = 0, high = 1, array = 3,6 min = 6
low = 2, high = 3, array = 1,5 min = 5
low = 0, high = 3, array = 3,6,1,5 min = 5
low = 4, high = 5, array = 7,2 min = 2
low = 6, high = 6, array = 1 min = 1
low = 4, high = 6, array = 7,2,1 min = 1
low = 0, high = 6, array = 3,6,1,5,7,2,1 min = 1

这告诉我,虽然FindMin()正在为这个测试用例返回正确的答案,但它偶然会这样做。我现在正在寻找原因......

(编辑)

一个问题是代码:

if (array[low] < array[high])
{
    min = array[low];
}
else if (array[low] > array[high]);  // <- stray semi-colon here
{
    min = array[high];
}

...不考虑array[low] == array[high]的情况。第一个比较应该是<=,或者第二个应该是>=,否则会出现min的返回值将是其初始值为0的情况,因为它们都不是if将适用。

(进一步编辑)

你有一个混乱的分号导致你的错误。我在上面标记的测试后的分号终止了语句。那么过早终止else if之后会出现另一个声明,无论前面的测试如何,总是将min设置为等于array[high]

将此代码更改为:

if (array[low] < array[high])
    {
    min = array[low];
    }
else 
    {
    min = array[high];
    }

...给出以下输出:

low = 0, high = 1, array = 3,6 min = 3
low = 2, high = 3, array = 1,5 min = 1
low = 0, high = 3, array = 3,6,1,5 min = 1
low = 4, high = 5, array = 7,2 min = 2
low = 6, high = 6, array = 1 min = 1
low = 4, high = 6, array = 7,2,1 min = 1
low = 0, high = 6, array = 3,6,1,5,7,2,1 min = 1

...你可以看到每个递归调用产生正确的结果。

答案 1 :(得分:1)

好的,现在我已经掌握了它的作用以及它是如何工作的。

这很简单。对于给定的数组,您可以进一步将其分为两部分。现在每个递归代码都必须在某个时刻停止,你的停止在两种情况下。

A) When the part this recursive needs to process is sized one.
B) When the part this recursive needs to process is sized two.

因此,当满足条件A时,您的函数只返回低,等于高。

当满足条件B时,您的函数会比较array[low]array[high],并返回较低值的索引。

如果递归函数必须处理超过2的范围,它将分为两部分,并将这两部分交给另外两个递归部分。

例如,对于这样的给定数组。

array[] = {1, 2, 3, 4, 5}

You will first split it to two parts of {1, 2} [0...1] and {3, 4, 5} [2...4].

    And now since the first part is of size 2, the index 0 gets returned because 1 is smaller than 2, obviously.

    And then the other part {3, 4, 5} gets divided again, to two parts, {3} [2...2], and {4, 5} [3...4].

        The first subpart of sized one, gets returned immediately, because it's of size one, return value = 2.

        And then the second part which is sized two, get compared and returned, return value = 3.

    Now these two return values (2 and 3) gets processed, comparing array[2] and array[3], array[2] is definitely smaller, so it returns 2.

Now those two return values (0 and 2) gets processed, comparing the two, we can see the minima is at index 0, of value 1.

您的代码存在缺陷,在最后一部分,您应该比较array[min1]array[min2]并返回min1min2

这是一团糟,希望你能理解。另一件事是我的语法,{data} [index range]