Swift中数组多峰值元素查找方案咨询(已有单峰值代码)
如何在Swift中查找数组的所有峰值元素
好问题!你原来的二分法实现确实能高效定位一个峰值,但要获取所有符合条件的峰值(或者统计峰值数量),我们需要换一种思路——毕竟二分法的核心是快速缩小范围找到单个峰值,而不是枚举所有可能的峰值点。
先明确峰值的定义
结合你给出的预期结果[5,6,4],我们这里的峰值指的是:
- 对于数组中间的元素(索引
i,满足0 < i < 数组长度-1):该元素同时大于左右两个相邻元素 - 对于数组首尾元素:只有当它大于唯一的相邻元素时才算峰值(不过你的示例数组里没有这种情况)
实现代码
1. 收集所有峰值元素
下面的函数会遍历数组,筛选出所有符合条件的峰值:
func findAllPeakElements(_ readings: [Int]) -> [Int] { guard readings.count >= 2 else { // 数组长度小于2时,不存在符合定义的峰值(若需调整规则,比如单元素算峰值,可修改这里) return [] } var peaks: [Int] = [] // 检查第一个元素 if readings[0] > readings[1] { peaks.append(readings[0]) } // 遍历检查所有中间元素 for i in 1..<readings.count - 1 { let current = readings[i] let leftNeighbor = readings[i-1] let rightNeighbor = readings[i+1] if current > leftNeighbor && current > rightNeighbor { peaks.append(current) } } // 检查最后一个元素 if let last = readings.last, let secondLast = readings.dropLast().last { if last > secondLast { peaks.append(last) } } return peaks }
2. 仅统计峰值数量
如果只需要获取峰值的个数,可以简化代码,避免存储所有峰值元素:
func countPeakElements(_ readings: [Int]) -> Int { guard readings.count >= 2 else { return 0 } var peakCount = 0 // 检查首元素 if readings[0] > readings[1] { peakCount += 1 } // 遍历中间元素 for i in 1..<readings.count - 1 { if readings[i] > readings[i-1] && readings[i] > readings[i+1] { peakCount += 1 } } // 检查尾元素 if let last = readings.last, let secondLast = readings.dropLast().last { if last > secondLast { peakCount += 1 } } return peakCount }
测试你的示例数组
用你提供的数组测试:
let testArray = [1,2,3,4,5,4,3,2,3,4,5,6,5,4,3,2,4,2] // 收集所有峰值 print(findAllPeakElements(testArray)) // 输出: [5, 6, 4],完全符合你的预期 // 统计峰值数量 print(countPeakElements(testArray)) // 输出: 3
为什么不用二分法?
你原来的二分法时间复杂度是O(log n),但它的逻辑是每次排除一半的数组,只能定位到一个峰值点——因为数组中可能存在多个峰值,它们分布在不同的区间,二分法无法覆盖所有区间,所以要获取所有峰值,必须采用O(n)的遍历方式,这是无法避免的(毕竟每个元素都需要和邻居对比才能确定是否为峰值)。
内容的提问来源于stack exchange,提问作者Atrain
相关产品推荐
相关产品推荐

