You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Haskell实现获取列表第二小值的secondSmallest函数

完善你的secondSmallest函数

看起来你已经搞定了secondSmallest的基础边界处理——空列表和单元素列表返回Nothing,接下来我们来完成核心逻辑,满足你提出的所有要求:返回列表的第二小值,若最小值重复出现,那这个最小值就视为第二小值。

先明确几个核心规则:

  • 列表长度小于2时,返回Nothing(你已经实现了)
  • 若最小值在列表中出现至少两次,第二小值就是这个最小值
  • 若最小值只出现一次,第二小值是列表中除最小值外的最小元素

下面给你两种实现思路,你可以根据需求选择:

思路一:直观排序法(适合新手理解)

先对列表排序,然后根据排序后的结果判断最小值是否重复,逻辑非常直白:

import Data.List (sort)

secondSmallest :: Ord a => [a] -> Maybe a
secondSmallest [] = Nothing
secondSmallest [x] = Nothing
secondSmallest xs = 
  let sortedList = sort xs
      smallest = head sortedList
      -- 检查排序后的第二个元素是否和最小值一致(说明最小值重复)
      hasDuplicateMin = sortedList !! 1 == smallest
  in if hasDuplicateMin
     then Just smallest
     else Just (sortedList !! 1)

这个方法的优点是容易看懂,但排序的时间复杂度是O(n log n),如果处理超大规模列表的话效率会稍低。

思路二:单次遍历高效法(性能更优)

我们可以在一次遍历中同时跟踪当前的最小值和第二小值,这样只需要O(n)的时间复杂度,效率更高:

secondSmallest :: Ord a => [a] -> Maybe a
secondSmallest [] = Nothing
secondSmallest [x] = Nothing
secondSmallest (x:y:rest) = go initialMin initialSecond rest
  where
    -- 初始化最小和第二小:取前两个元素的大小关系
    (initialMin, initialSecond) = if x < y then (x, y) else (y, x)
    
    -- 遍历函数:持续跟踪当前最小和第二小值
    go currentMin currentSecond [] = 
      -- 遍历结束后,判断是否存在重复最小值
      if currentMin == currentSecond
      then Just currentMin
      else Just currentSecond
    go currentMin currentSecond (z:zs)
      | z < currentMin = 
          -- 遇到比当前最小值更小的,更新最小和第二小
          go z currentMin zs
      | z == currentMin = 
          -- 遇到重复的最小值,把第二小值也设为最小值
          go currentMin currentMin zs
      | z < currentSecond = 
          -- 遇到比第二小值小但不比最小值小的,更新第二小
          go currentMin z zs
      | otherwise = 
          -- 当前元素不影响最小和第二小,继续遍历
          go currentMin currentSecond zs

这个方法只需要遍历列表一次,而且能精准处理所有边界情况,比如全是相同元素的列表、最小值多次出现的列表等。

测试验证你的示例

用你给出的例子验证:

  • secondSmallest [1.0] → Nothing ✔️
  • secondSmallest [1,1,2] → Just 1 ✔️
  • secondSmallest [5,3,7,2,3,1] → Just 2 ✔️

再补充几个测试场景:

  • secondSmallest [2,2,2] → Just 2(所有元素都是最小值)
  • secondSmallest [3,1,4,1,5] → Just 1(最小值重复)
  • secondSmallest [10,9,8,7,6] → Just 7(最小值只出现一次)

内容的提问来源于stack exchange,提问作者Aelin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:33:52