Java数组统一元素最少移除操作代码出现IndexOutOfBoundsError问题
数组统一元素最少操作次数代码的IndexOutOfBoundsError排查
错误根源分析
抛出IndexOutOfBoundsError的直接原因是最后遍历list并删除元素的循环逻辑错误:
for(int i=0;i<n;i++){ if((list.get(i))!=(list.get(res))){ list.remove(i); count++; } }
存在两个致命问题:
- 索引越界:循环条件用了原始数组长度
n,但每次调用list.remove(i)都会让list长度减1。当i增长到超过当前list的实际长度时,list.get(i)就会触发索引越界异常。 - 元素遗漏:删除元素后,
list中后续元素会自动前移一位,但循环的i会继续自增,导致跳过了前移后的元素判断。
另外还有一个潜在问题:用!=判断Integer类型是否相等,当数值超出-128~127范围时,!=会比较对象引用而非实际数值,应该改用equals()方法。
修复方案
方案1:倒序遍历删除
倒序遍历可以避免删除元素后索引混乱的问题,因为删除后面的元素不会影响前面未遍历的索引:
int count = 0; Integer target = list.get(res); for (int i = list.size() - 1; i >= 0; i--) { if (!list.get(i).equals(target)) { list.remove(i); count++; } }
方案2:使用迭代器遍历删除
这是Java集合遍历时删除元素的标准做法,迭代器会自动处理元素前移的问题:
int count = 0; Integer target = list.get(res); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { if (!iterator.next().equals(target)) { iterator.remove(); count++; } }
更高效的逻辑优化
其实原代码的核心需求是找到出现次数最多的元素,最少操作次数=总元素数-该元素出现次数,完全不需要用List来统计,直接用数组或哈希表统计频率更高效:
Scanner sc = new Scanner(System.in); int test = sc.nextInt(); while (test > 0) { int n = sc.nextInt(); int[] arr = new int[n]; // 假设元素模n后落在0~n-1范围,若元素范围不确定可改用HashMap int[] freq = new int[n]; for (int i = 0; i < n; i++) { arr[i] = sc.nextInt(); freq[arr[i] % n]++; } // 找出最大出现次数 int maxFreq = 0; for (int f : freq) { if (f > maxFreq) { maxFreq = f; } } // 最少操作次数=总元素数-最大频率 System.out.println(n - maxFreq); test--; }
内容的提问来源于stack exchange,提问作者6088 Jeevana
相关产品推荐
相关产品推荐

