【问题标题】:Recursive binary search (integer)递归二分查找(整数)
【发布时间】:2021-04-08 23:20:23
【问题描述】:

我已经编写了这个基于递归的二进制搜索算法,但我无法理解错误的原因。

    // Only a sorted array must be entered for binary search to work
    public int binarySearch(int searchFor, int[] inArray, int from, int to){
        if (to >= from){
            int mid = (to-from)/2 + from;
            
            if (inArray[mid] == searchFor){
                return inArray[mid];
            } else if (inArray[mid] < searchFor){
                binarySearch(searchFor, inArray, ++mid, to);
            } else if (inArray[mid] > searchFor){
                binarySearch(searchFor, inArray, from, ++mid);
            }
        }
        return -1;
    }

线程“主”java.lang.StackOverflowError 中的异常

at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)

【问题讨论】:

  • 我认为您需要在 else if 调用中添加返回
  • 检查此示例与您的代码非常相似。 Example。正如@VedantTerkar 提到的,您在“else if”指令中都错过了 return 这个词。
  • 添加输入值以了解问题
  • 除了缺少的returns,当你向左走时,你也会错误地计算上限:你想要mid - 1这里。 (我认为您应该返回索引mid,而不是您已经知道的值inArray[mid]。)
  • 而且你应该有办法处理找不到元素的事实。

标签: java algorithm recursion search binary-search


【解决方案1】:

几个问题和评论:

  • 在最后一种情况下,++mid 的值作为 binarySearch 的参数是错误的。在这种情况下,该值应该比mid 少一

  • 我也会在此处投票反对使用++mid--mid,因为这表明mid 更改值很重要,这不是必需的。你应该在第一种情况下传递mid+1,在第二种情况下传递mid-1

  • binarySearch 返回一个 int,但是当您的代码递归调用它时,它不会对该返回值做任何事情。

    你应该返回那个值。所以:

                } else if (inArray[mid] < searchFor){
                    return binarySearch(searchFor, inArray, mid+1, to);
    //              ^^^^^^                                  ^^^^^
                } else if (inArray[mid] > searchFor){
                    return binarySearch(searchFor, inArray, from, mid-1);
    //              ^^^^^^                                        ^^^^^
                }
    
  • 表达式(to-from)/2 + from(from+to)/2 的冗长方式...

【讨论】:

  • (表达式(from + to) / 2 可能会溢出大数。使用(to - from) / 2 + from 可以防止溢出。这里可能不是问题。)
  • 表达式(to-from)/2 + from是防止整数溢出的防御措施:)
  • 是的,在处理至少 2³⁰ 个整数(即 4GB)的数组时,这是必要的预防措施。
【解决方案2】:

除了在binarySearch的递归调用中添加return之外,还有一些逻辑缺陷:

  • mid 应该递减以捕获左侧的值:
    return binarySearch(searchFor, inArray, from, --mid);
  • 应该检查有效的midfromto 值以适合输入数组

因此,该方法应如下所示:

public static int binarySearch(int searchFor, int[] inArray, int from, int to) {
        if (to >= from && from > -1 && to <= inArray.length) {
            int mid = (to-from)/2 + from;
            
            if (mid >= inArray.length) {
                return -1;
            }
            
            // System.out.printf("from=%d to=%d mid=%d val=%d%n", from, to, mid, inArray[mid]); // debug print
            if (inArray[mid] == searchFor) {
                return inArray[mid];
            } else if (inArray[mid] < searchFor){
                return binarySearch(searchFor, inArray, ++mid, to);
            } else {
                return binarySearch(searchFor, inArray, from, --mid);
            }
        }
        return -1;
    }
}

测试:

public static int binarySearch(int searchFor, int... inArray) {
    System.out.printf("Searching for %d in %s%n", searchFor, Arrays.toString(inArray));
    return binarySearch(searchFor, inArray, 0, inArray.length);
}

System.out.println(binarySearch(10));
    System.out.println(binarySearch(10, 10));
    System.out.println(binarySearch(10, 1));
    System.out.println(binarySearch(10, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch( 0, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(21, 0, 1, 5, 8, 10, 21));
    
    System.out.println(binarySearch(10, 0, 1, 3, 5, 8, 10, 21));
    System.out.println(binarySearch( 0, 0, 1, 5, 8, 10, 15, 21));
    System.out.println(binarySearch(21, 0, 1, 5, 8, 10, 16, 21));
    
    System.out.println(binarySearch(30, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(-1, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(7, 0, 1, 5, 8, 10, 21));

输出:

Searching for 10 in []
-1
Searching for 10 in [10]
10
Searching for 10 in [1]
-1
Searching for 10 in [0, 1, 5, 8, 10, 21]
10
Searching for 0 in [0, 1, 5, 8, 10, 21]
0
Searching for 21 in [0, 1, 5, 8, 10, 21]
21
Searching for 10 in [0, 1, 3, 5, 8, 10, 21]
10
Searching for 0 in [0, 1, 5, 8, 10, 15, 21]
0
Searching for 21 in [0, 1, 5, 8, 10, 16, 21]
21
Searching for 30 in [0, 1, 5, 8, 10, 21]
-1
Searching for -1 in [0, 1, 5, 8, 10, 21]
-1
Searching for 7 in [0, 1, 5, 8, 10, 21]
-1

【讨论】:

    猜你喜欢
    • 2015-12-16
    • 2020-11-13
    • 1970-01-01
    • 2015-12-02
    • 2011-02-08
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多