【问题标题】:using recursive method for trinary search使用递归方法进行三元搜索
【发布时间】:2014-08-31 15:14:16
【问题描述】:

我正在编写一个递归方法,它不是执行二分搜索算法,而是将一个数组分成三个并使用三元搜索算法。我相当肯定我的递归案例是正确的,但我的基本案例似乎有问题。基本情况,如果数组包含两个或更少的值,应该以非递归方式检查值是否在数组中并返回索引。如果未找到该值,则返回 -1。

由于我无法弄清楚的原因,这个方法无论如何都会返回 -1。不管数组的大小,或者数组是否包含值。方法如下。

public static int trinarySearch(int[] array, int x, int low, int high) {

    if (high - low < 3) { //BASE CASE.
        for (int i = low; i < high; i++) {
            if (array[i] == x) {
                return i;
            }
        }
        return -1;
    } else { //RECURSIVE CASE.

        int firstThird = low + (high - low) / 3;
        int secondThird = low + 2 * (high - low) / 3;

        if (x <= array[firstThird]) {
            return trinarySearch(array, x, low, firstThird - 1);
        } else if (x <= array[secondThird]) {
            return trinarySearch(array, x, firstThird + 1, secondThird - 1);
        } else { // must be (x > array[secondThird])
            return trinarySearch(array, x, secondThird + 1, high);
        }
    }
}

在我的测试代码中,我只是将数组设置为 int[] array = {1, 2, .....}

假设我搜索 int 2,它在数组中。我在测试代码中设置了一个数组,并将方法调用为 trinarySearch(array, 2, 0, array.length-1)。它每次都打印-1。方法有问题,还是我只是设置了测试代码错误?

【问题讨论】:

  • x
  • 正如@MitchWheat 所说,递归情况下的测试与递归调用的限制不一致,并且基本情况在之前 high 停止。重新思考。插入一些打印语句或使用调试器来查看您的心智模型中的错误所在。

标签: java arrays algorithm recursion


【解决方案1】:

您似乎混淆了lowhigh 的逻辑。通常,您会将要检查的子数组定义为从low(包括)开始,到high(不包括)结束。

您使用 high 包容性(正如我从您使用 array.length-1 的示例调用中了解到的那样),然后像这样循环

for (int i = low; i < high; i++) {

不访问array[high]

快速解决方法是将 &lt; 更改为 &lt;= 并且您的代码运行良好。但是,我建议使用标准定义(高排他性),因为它还简化了代码的其他部分:

  • 您不需要任何容易出错的+1-1 索引修复(不要忘记在递归情况下将&lt;= 更改为&lt;)。
  • high-low 是要检查的子数组的大小,因此您可以使用 high-low &lt;= 3,它更清楚地表明您的基本情况处理长度为 3 的数组。

【讨论】:

  • 它现在只适用于数组前三分之一的值。递归情况中的其他两种情况不起作用,在数组的最后三分之二中搜索值时仍然返回-1。
【解决方案2】:

我想你没听懂 Heuster 的回答。这就是我会做的事情,在我看来,Heuster 也是这么说的:

public static int trinarySearch(int[] array, int x, int low, int high) {

        if (high - low < 3) { //BASE CASE.
            for (int i = low; i < high; i++) {
                if (array[i] == x) {
                    return i;
                }
            }
            return -1;
        } else { //RECURSIVE CASE.
            int firstThird = low + (high - low) / 3;
            int secondThird = low + 2 * (high - low) / 3;

            if (x < array[firstThird]) {
                return trinarySearch(array, x, low, firstThird);
            } else if (x < array[secondThird]) {
                return trinarySearch(array, x, firstThird, secondThird);
            } else { // must be (x > array[secondThird])
                return trinarySearch(array, x, secondThird, high);
            }
        }
    }

【讨论】:

    【解决方案3】:

    您刚刚错过了递归部分中的一个重要条件,即if(x==splitingIndex)

    我对您的代码进行了一些更改,它的工作原理
    查看更改

    public static int trinarySearch(int[] array, int x, int low, int high) {
    
        if (high - low < 3) { 
            //BASE CASE.
            for (int i = low; i < high; i++) {
                if (array[i] == x) {
                    return i;
                }
            }
            return -1;
        } else { //RECURSIVE CASE.
    
            int firstThird = low + (high - low) / 3;
            int secondThird = low + 2 * (high - low) / 3;
    
            if(x == array[firstThird])
            {
                return firstThird;
            }
            else if (x < array[firstThird]) {
                return trinarySearch(array, x, low, firstThird - 1);
            }
    
            if(x == array[secondThird])
            {
                return secondThird;
            }
            else if (x < array[secondThird]) {
                return trinarySearch(array, x, firstThird + 1, secondThird - 1);
            }
    
    
    
                return trinarySearch(array, x, secondThird + 1, high);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      • 2010-09-20
      • 2012-01-30
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多