将Arrays.copyOfRange传入方法实现二分查找时始终返回0的问题
你的二分查找返回0的问题分析与修复方案
我一眼就看出问题出在数组切割后的索引偏移没处理!你用Arrays.copyOfRange把数组切成两半后,新数组的索引是从0重新开始的,但你返回的position一直初始化为0,完全没考虑原数组的索引位置,这就是为什么每次都返回0。
先拆解你的核心问题:
- 当你把数组切成左半部分或者右半部分时,新数组的元素在原数组里的位置是有偏移的,比如原数组长度为8,中间索引是4,如果你取右半部分(索引4到7),新数组的第0个元素对应原数组的第4个元素,但你的代码里没把这个偏移量加进去。
- 另外,你的代码看起来像是打算用循环或者递归,但目前的逻辑只执行了一次判断,没有循环/递归的终止条件,也没处理数组长度为0的情况。
修复后的代码示例
我给你改了两种版本,一种是不切割数组,只操作索引范围(更高效,不用创建新数组),另一种是保留你用Arrays.copyOfRange的思路,但正确处理索引偏移:
版本1:推荐的索引范围法(无数组拷贝,性能更好)
public static int findNumber(int[] array, int number) { int left = 0; int right = array.length - 1; while (left <= right) { int mid = left + (right - left) / 2; // 避免溢出,比(left+right)/2更安全 if (array[mid] == number) { return mid; // 直接返回原数组的索引 } else if (array[mid] < number) { left = mid + 1; // 目标在右半部分,左边界右移 } else { right = mid - 1; // 目标在左半部分,右边界左移 } } return -1; // 没找到返回-1,约定俗成的错误标识 }
版本2:保留Arrays.copyOfRange的递归版(处理索引偏移)
如果你坚持要用数组拷贝的方式,就得把每次切割后的偏移量传递下去:
import java.util.Arrays; public static int findNumber(int[] array, int number) { return findNumberWithOffset(array, number, 0); } // 辅助方法,offset是当前数组在原数组中的起始索引偏移 private static int findNumberWithOffset(int[] array, int number, int offset) { if (array.length == 0) { return -1; // 空数组,没找到 } int mid = array.length / 2; if (array[mid] == number) { return offset + mid; // 原数组的索引 = 偏移量 + 当前数组的中间索引 } else if (array[mid] < number) { // 取右半部分,偏移量加上当前数组左半部分的长度(mid+1) int[] rightHalf = Arrays.copyOfRange(array, mid + 1, array.length); return findNumberWithOffset(rightHalf, number, offset + mid + 1); } else { // 取左半部分,偏移量不变 int[] leftHalf = Arrays.copyOfRange(array, 0, mid); return findNumberWithOffset(leftHalf, number, offset); } }
为什么你的原代码返回0?
你原代码里position初始化为0,不管找到没找到(或者根本没正确判断找到的情况),最后都返回0。而且你没有处理递归或循环的逻辑,只做了一次中间值判断,就算中间值不等于目标,也没有继续查找,直接返回了初始的0。
另外,注意二分查找的终止条件:当左边界超过右边界时,说明目标不存在,应该返回-1而不是0,这样调用者能区分“找到在索引0”和“没找到”的情况。
内容的提问来源于stack exchange,提问作者Rishabh Mandayam
相关产品推荐
相关产品推荐

