GeeksforGeeks"仅重复元素计数"问题Java代码输出0 0的调试
代码缺陷分析与修复方案
核心问题
代码输出0 0的本质原因是二分查找定位重复值的逻辑漏检了循环退出时的边缘相邻位置,导致重复值变量repNumber始终保持初始值0,后续基于0值计算索引完全失效,最终返回错误结果。
复现路径
可以用一个极小的测试用例完全复现这个问题:
输入数组[1,2,3,4,4],长度n=5,重复元素为4、重复次数2。走一遍原代码的流程:
- 数组首尾元素1和4不相等,跳过全数组同值的分支。
- 初始化low=0、high=4、repNumber=0。
- 进入二分循环(循环条件为
high-low >1):- 第一次迭代:mid=2,arr[mid]=3,相邻元素2、4均不相等,未触发重复检测。
- 连续值校验:arr[low]+(mid-low) =1 +2=3,与arr[mid]相等,因此将low更新为mid+1=3。
- 此时low=3、high=4,两者差值为1,不满足循环条件,直接退出循环。
- 全程没有给repNumber赋值,repNumber保持0。后续分支判断:
- 0不等于arr[0]=1,也不等于arr[n-1]=4,进入else分支。
- 基于repNumber=0做二分查找:找-1返回-1、找1返回索引0,最终计算得到startIndex=0、endIndex=0,返回结果(0,0),完全匹配测试中遇到的错误。
长度28566的大测试用例触发的是完全相同的路径:二分调整过程中low和high最终变为相邻值,循环提前退出,没有检测到重复块就在这两个相邻位置上,导致repNumber始终为0。
缺陷根源
原二分循环的退出条件是high-low >1,也就是当low和high刚好相邻时,循环直接结束。但此时重复块大概率就落在这两个相邻的位置上——因为二分的调整逻辑已经把重复块的范围收敛到这两个点之间了,但代码只在循环内部检查mid位置的重复情况,从未检查循环退出后low、high位置的相邻元素,直接漏掉了边缘场景。
修复方案
在二分循环全部执行结束后,补充对low、high两个相邻位置的重复检测,确保不会遗漏循环退出时的重复块:
// 在原有while循环结束后,增加这段补检逻辑 if (repNumber == 0) { // 检查low位置是否属于重复块 if (low < n-1 && arr[low].equals(arr[low+1])) { repNumber = arr[low]; } // 检查high位置是否属于重复块 if (repNumber ==0 && high >0 && arr[high].equals(arr[high-1])) { repNumber = arr[high]; } }
补检逻辑触发后,就可以正确拿到repNumber的值,后续基于repNumber计算重复次数的分支逻辑就能正常运行,得到正确的结果。
额外优化提示
- 原代码中判断相邻元素相等时,因为数组元素是Integer类型,建议用
equals做值比较,避免缓存范围外的整数用==比较失效的问题。 - 原二分的调整逻辑本身是正确的,基于连续数组的性质(无重复时arr[i] = arr[low] + (i-low))可以快速收敛到重复块的范围,只需要补上边缘检测即可适配全部测试用例。
内容的提问来源于stack exchange,提问作者Divyanshu Rathore
相关产品推荐
相关产品推荐

