判断和为K的子数组是否存在的Java代码运行报错排查
问题背景
实现目标:判断给定数组中是否存在元素和恰好等于K的连续子数组。
当前问题:编写的Java代码在部分测试场景下触发运行时错误,报错截图如下:
原有问题代码
int sum = 0, count = 0; HashMap<Integer, Integer> hm = new HashMap<>(); hm.put(0, 1); for (int i = 0; i < n; i++) { sum += arr[i]; if (hm.containsKey(sum - k)) { count = hm.get(sum - k); count++; hm.put(sum, count); } else { hm.put(sum, 1); } } if (count > 0) { System.out.println("Yes"); } else { System.out.println("No"); }
问题根因
代码存在3处核心错误,直接导致运行异常、结果不符合预期:
- 结果计数逻辑错误:命中
sum - k前缀和时,应该把该前缀和的出现次数累加到结果count上,而不是把count直接赋值为该次数后自增,这会完全丢失之前累加的计数结果。 - 前缀和次数更新逻辑完全错位:不管是否命中
sum -k,都需要单独维护当前前缀和sum的出现次数——原有逻辑在命中分支里把错误的count值写入sum对应的键,未命中分支直接给sum写入1,会覆盖同一前缀和的历史出现次数,后续计算时哈希表内的计数完全错乱,极端场景下会触发逻辑异常。 - 类型溢出风险:用
int存储前缀和,当数组长度大、元素数值高时,累加值很容易超过int的取值范围触发溢出,既会导致结果错误,部分场景下也会引发运行时异常。
修正方案
修正逻辑后代码如下,可覆盖所有测试场景:
// 前缀和用long类型避免整数溢出 long sum = 0; int count = 0; HashMap<Long, Integer> prefixMap = new HashMap<>(); // 初始化前缀和0出现1次,对应从数组头部开始的子数组场景 prefixMap.put(0L, 1); for (int i = 0; i < n; i++) { sum += arr[i]; long target = sum - k; // 存在符合要求的前缀和,累加对应出现次数 if (prefixMap.containsKey(target)) { count += prefixMap.get(target); } // 更新当前前缀和的出现次数 prefixMap.put(sum, prefixMap.getOrDefault(sum, 0) + 1); } System.out.println(count > 0 ? "Yes" : "No");
优化提示:如果题目仅需要判断是否存在符合要求的子数组,不需要统计总数量,那么在第一次命中
target时就可以直接输出"Yes"终止程序,不需要遍历完整数组,执行效率更高。
内容的提问来源于stack exchange,提问作者Shabbir Katlariwala
相关产品推荐
相关产品推荐

