我一直在尝试在OCaml中实现一个函数,该函数返回排序列表中最小的缺失数字(大于0)。
这是我做过的事情
let getMissingNumber l =
let rec find min = function
| [] -> min
| t :: [] -> t + 1
| t1 :: t2 :: r -> if t2 - t1 > 1 then t1 + 1 else find min (t2 :: r)
in find 1 l;;
结果如下:
# getMissingNumber [1; 4; 5];;
- : int = 2
# getMissingNumber [1; 2; 5];;
- : int = 3
# getMissingNumber [1; 2; 3];;
- : int = 4
# getMissingNumber [3; 4; 5];;
- : int = 6
所有结果都是正确的,但最后一个。有什么建议吗?
答案 0 :(得分:1)
问题是如果list包含多个元素,那么这个函数永远不会返回1,只是因为| t :: [] -> t + 1
(如果t > 0
)。
因此我们可以将| t :: [] -> t + 1
替换为| t :: [] -> min
,但在这种情况下,[1; 2; 3; ...; n]
形式的所有列表都会出现问题,因为在| t1 :: t2 :: r
分支中我们不要更改min
,因此我们最终会返回1(即使正确答案是n+1
)。
所以我们需要“更新”min
,但有趣的是,如果我们将find min (t2 :: r)
替换为find (t2 + 1) (t2 :: r)
,我们将返回原来的函数。
实际上,此函数搜索的最小缺失数大于最小呈现数。主要问题是您没有充分理由区分[t]
和t1::t2::r
。
let getMissingNumber l =
let rec find min = function
| [] -> min
| t::r ->
if t > min then min
else find (t + 1) r
in find 1 l
答案 1 :(得分:0)
如果输入列表可能以小于1的值开头,那么您还需要跳过这些。
let getMissingNumber l =
let rec find min = function
| [] -> min
| h :: t when min < t -> min
| h :: t when min = t -> find (min+1) t
| _ :: t -> find min t
in find 1 l