Codewars数组找峰值问题:代码未通过测试的疑问
Codewars峰值检测算法问题解析
题目规则回顾
- 数组首尾元素不视为峰值
- 平台段峰值:仅当平台段两侧都有更小的元素时,平台的起始位置才算峰值(比如
[1,2,2,2,1]的位置1是峰值;而[1,2,2,2,3]右侧是更大元素、[1,2,2,2,2]两侧无更小元素,都不算峰值) - 示例输入:
[3,2,3,6,4,1,2,3,2,1,2,3],预期输出:{pos: [3,7], peaks: [6,3]}
你的疑问解答
你认为示例中只有位置3的6是峰值,是忽略了位置7的元素:
位置7的元素是3,左侧是位置6的2,右侧是位置8的2,满足比左右两侧元素都大的条件,且不是首尾元素,属于有效峰值。
你的代码问题分析
代码逻辑存在核心缺陷:
- 初始化直接添加位置1的元素,不符合规则——位置1的元素不一定是峰值
- 遍历仅比较当前元素与最后一个暂存元素,只保留遍历到的最大元素,完全没检查右侧是否有更小元素,也无法处理多峰值场景
- 完全未实现平台段的峰值判定逻辑
修正后的代码
import java.util.*; public class PeakPicker { public static Map<String, List<Integer>> getPeaks(int[] arr) { Map<String, List<Integer>> result = new HashMap<>(); List<Integer> positions = new ArrayList<>(); List<Integer> peaks = new ArrayList<>(); if (arr.length < 3) { result.put("pos", positions); result.put("peaks", peaks); return result; } int currentPeakPos = -1; boolean isAscending = false; for (int i = 1; i < arr.length; i++) { if (arr[i] > arr[i-1]) { // 进入上升阶段,记录潜在峰值位置 currentPeakPos = i; isAscending = true; } else if (arr[i] < arr[i-1] && isAscending) { // 上升后出现下降,确认峰值有效 positions.add(currentPeakPos); peaks.add(arr[currentPeakPos]); isAscending = false; currentPeakPos = -1; } // 元素相等时不做操作,继续观察后续趋势,自然处理平台段逻辑 } result.put("pos", positions); result.put("peaks", peaks); return result; } }
代码说明
- 先判断数组长度,不足3直接返回空结果(无法形成峰值)
- 用
currentPeakPos记录上升阶段的潜在峰值位置,isAscending标记是否处于上升趋势 - 遍历过程中:
- 上升趋势时更新潜在峰值位置
- 上升后出现下降时,确认峰值有效并加入结果
- 平台段(元素相等)不做操作,直到趋势变化,自动适配平台段峰值规则
内容的提问来源于stack exchange,提问作者Amos Machora
相关产品推荐
相关产品推荐

