Java递归实现首尾位置查找遇ArrayIndexOutOfBounds异常求助
问题分析与修复方案
你遇到的ArrayIndexOutOfBounds异常,核心原因是代码缩进错误导致逻辑分支混乱,加上访问数组元素时未做边界校验,直接访问nums[mid+1]或nums[mid-1]时触发了越界。
关键问题拆解
- 缩进引发的逻辑错误:
if (!wh)块未用大括号包裹,导致后续的索引判断代码不属于else分支,逻辑完全混乱,触发错误的递归调用,最终导致索引越界。 - 无边界的数组访问:当
mid是数组最后一个索引时,nums[mid+1]直接越界;当mid是第一个索引时,nums[mid-1]同样越界。 - 冗余的边界判断:
if (start == -1 || end == -1)完全没必要,初始调用的start和end都是合法范围,递归传递的参数也不会出现负数。
修复后的代码
import java.util.Arrays; public class DSA_First_Last_Occurence_Rec { public static void main(String[] args) { int[] arr = {2,2}; int ae = 2; System.out.println(Arrays.toString(searchRange(arr,ae))); } public static int[] searchRange(int[] nums, int target) { return search(nums, target); } private static int[] search(int[] nums, int target) { int[] ans = {-1,-1}; ans[0] = help(nums, target, 0, nums.length-1, true); if (ans[0] != -1) ans[1] = help(nums, target, 0, nums.length-1, false); return ans; } private static int help(int[] nums, int target, int start, int end, boolean findFirst) { // 递归终止条件:范围无效直接返回-1 if (start > end) { return -1; } int mid = start + (end - start) / 2; if (nums[mid] == target) { // 查找第一个出现的位置 if (findFirst) { // 若mid是当前范围的起始点,或前一个元素不等于目标值,当前就是第一个位置 if (mid == start || nums[mid-1] != target) { return mid; } else { // 否则递归向左查找 return help(nums, target, start, mid - 1, true); } } else { // 查找最后一个出现的位置 // 若mid是当前范围的终点,或后一个元素不等于目标值,当前就是最后一个位置 if (mid == end || nums[mid+1] != target) { return mid; } else { // 否则递归向右查找 return help(nums, target, mid + 1, end, false); } } } else if (target < nums[mid]) { // 目标值在左半区,递归缩小范围 return help(nums, target, start, mid - 1, findFirst); } else { // 目标值在右半区,递归缩小范围 return help(nums, target, mid + 1, end, findFirst); } } }
修改说明
- 修复逻辑分支:给查找分支加上大括号,确保代码逻辑分支清晰,避免执行错误的代码块。
- 添加边界校验:通过判断
mid == start或mid == end,避免访问数组越界的索引。 - 简化递归逻辑:去掉冗余的while循环,纯递归实现二分查找,代码可读性更高。
- 语义化变量名:将
wh改为findFirst,让变量含义更直观。
现在测试{2,2}数组会正确输出[0,1],{1,2,2,2,3,4}场景也能正常返回[1,3]。
内容的提问来源于stack exchange,提问作者Pushkar
相关产品推荐
相关产品推荐

