关于峰值查找代码的逻辑解析请求——为何这些条件能找到峰值元素?
Ruby数组峰值查找代码逻辑全解析
问题背景
你需要实现一个Ruby方法,接收数字数组,返回所有峰值元素的数组。峰值定义:
- 首尾元素:大于唯一相邻元素即为峰值
- 中间元素:同时大于左右两个相邻元素即为峰值
你给出的代码实现如下:
def peak_finder(arr) peaks = [] arr.each_index do |i| left = arr[i - 1] # left most num mid = arr[i] # mid num right = arr[i + 1]# right most num if i == 0 && mid > right peaks << mid elsif i == arr.length - 1 && mid > left peaks << mid elsif !left.nil? && !right.nil? && mid > right && mid > left #do not understand this condition peaks << mid end end peaks end p peak_finder([1, 3, 5, 4]) # => [5]
你的疑问是:这些条件如何实现峰值查找,尤其是中间元素的判断逻辑。
逐行拆解代码逻辑
我们可以把代码的判断逻辑分成三个场景,对应数组的首元素、尾元素、中间元素:
1. 首元素的判断(i == 0 && mid > right)
当遍历到数组第一个元素时(索引i=0),它只有右侧一个相邻元素(right = arr[1])。按照峰值定义,只要当前元素mid大于右侧邻居right,就符合峰值要求,直接加入peaks数组。
2. 尾元素的判断(i == arr.length - 1 && mid > left)
当遍历到数组最后一个元素时(索引i = arr.length - 1),它只有左侧一个相邻元素(left = arr[-2])。只要当前元素mid大于左侧邻居left,就符合峰值要求,加入peaks数组。
3. 中间元素的判断(!left.nil? && !right.nil? && mid > right && mid > left)
这个条件可以拆成两部分理解:
!left.nil? && !right.nil?:确保当前元素既不是首元素也不是尾元素。因为首元素的left = arr[-1](Ruby中数组负索引取倒数元素,但这里首元素已经单独处理了),尾元素的right = arr[arr.length]会返回nil,所以这两个判断是为了筛选出真正的中间元素(有左右两个有效邻居)。mid > right && mid > left:严格符合中间元素的峰值定义——当前元素必须同时大于左侧和右侧的相邻元素,两个条件都满足才算是峰值。
结合示例走一遍流程
用你给出的测试用例[1, 3, 5, 4]来模拟遍历过程:
- 索引
0:mid=1,right=3,1>3不成立,不加入peaks - 索引
1:left=1,mid=3,right=5,3>1但3>5不成立,不加入 - 索引
2:left=3,mid=5,right=4,5>3且5>4,满足条件,加入peaks - 索引
3:mid=4,left=5,4>5不成立,不加入
最终peaks数组就是[5],和预期结果一致。
内容的提问来源于stack exchange,提问作者Hazel Alvarez
相关产品推荐
相关产品推荐

