如何编写函数来获取列表中最小int的位置?

时间:2010-10-19 20:37:15

标签: list ocaml

原型必须是:

listMinPos(lst)

我能够使用两个参数(列表和索引)编写相同的内容,但我甚至无法想到如何只使用list参数。

以下内容必须符合:

  1. 只有1个参数(列表)。
  2. 没有外部图书馆。
  3. 函数应该是递归的(函数内部没有'let')

1 个答案:

答案 0 :(得分:3)

我有一个轻微欺骗的解决方案:我返回最小元素的位置,但不仅仅是。还返回最小元素的值。

let rec min_pos = function
  | [] -> invalid_arg "min_pos"
  | [x] -> (0, x)
  | hd::tl ->
    let p, v = min_pos tl in
    if hd < v then (0, hd) else (p + 1, v)

(正如Pascal Cuoq注意到的那样,仍有一个let p, v = .. in ..;它可以被match .. with p, v -> ..取代。请参阅评论。)

放松第二个约束的另一个解决方案(没有外部库):

let rec min_pos = function
  | [] -> invalid_arg "min_pos"
  | [x] -> 0
  | hd::tl ->
    let p = min_pos tl in
    if hd < List.nth tl p then 0 else p + 1

效率低下,但我认为如果不传递更多信息,你可以做得更好。

修改

我不明白这是一个功课。是否存在反对完成家庭作业问题解决方案的政策?

无论如何,在这种情况下,我认为你给出的限制列表并不像我认为的那样是一种强迫创造力的约束,而且我认为如果能给出更好的解决方案,你可以打破它们。

因此,我建议使用本地let

let min_pos li =
  let rec min_pos = function
    | [] -> invalid_arg "min_pos"
    | [x] -> (0, x)
    | hd::tl ->
      let p, v = min_pos tl in
      if hd < v then (0, hd) else (p + 1, v)
  in fst (min_pos li)

尾递归版:

let min_pos li =
  let rec min_pos mini mpos cur_pos = function
    | [] -> mpos
    | hd::tl ->
      if hd < mini
      then min_pos hd cur_pos (cur_pos + 1) tl
      else min_pos mini mpos (cur_pos + 1) tl
  in match li with
     | [] -> invalid_arg "min_pos"
     | hd::tl -> min_pos hd 0 1 tl