【问题标题】:Ocaml: How can I delete all the duplicate element from list?Ocaml:如何从列表中删除所有重复的元素?
【发布时间】:2022-04-02 03:04:48
【问题描述】:

在学习 Ocaml 时,我看到了一个从列表中删除重复元素的代码。

let rec remove =
function
  | []       -> []
  | x::[]    -> x::[]
  | x::y::tl ->
     if x=y then remove (y::tl)
     else x::remove (y::tl)

但是,我发现这段代码只会删除连续的重复项,所以如果我尝试一些重复项,它们会单独占据一个位置,例如 [6;6;8;9;4;2;5;1;5;2; 3],代码处理连续重复的6,但不处理分离的2或5。

我怎样才能完全使列表只有独特的元素? 比如删除 [6;6;8;9;4;2;5;1;5;2;3] -> [6;8;9;4;2;5;1;3]。

附言我设法删除了先出现的重复项,但不知道如何删除后面出现的重复项。

【问题讨论】:

  • 先排序就好了。然后所有重复项彼此相邻。
  • 排序可以是一个关键,但我现在想要的是在不改变任何元素顺序的情况下删除。无论如何,排序是个好主意
  • 对,那么您必须跟踪到目前为止遇到的每个元素,并检查每个后续元素。

标签: list duplicates ocaml


【解决方案1】:

根据您的描述,您编写了算法的二次版本。 还有一个 O(n log n) 版本,使用一组已经看到的值:

let remove_duplicates (type a) (l: a list) =
  let module S = Set.Make(struct type t = a let compare = compare end) in
  let rec remove acc seen_set = function
      | [] -> List.rev acc
      | a :: rest when S.mem a seen_set -> remove acc seen_set rest
      | a :: rest -> remove (a::acc) (S.add a seen_set) rest in
  remove [] S.empty l

(上面的代码使用了多态比较,你可能想在实际代码中提供一个比较函数参数)

【讨论】:

  • 一个 Hashtbl 将把它降低到 O(n)。
【解决方案2】:

这个问题已经很老了,但这是一个不使用集合的解决方案,以防万一:

let rec remove_duplicates l =
  let rec contains l n =
    match l with
    | [] -> false
    | h :: t ->
      h = n || contains t n
  in
  match l with
  | [] -> []
  | h :: t ->
    let acc = remove_duplicates t in
    if contains acc h then acc else h :: acc
;;

【讨论】:

    【解决方案3】:

    我终于想通了。 在没有排序的情况下,我做了一个元素检查和元素删除功能,所以我可以检查列表的尾部是否有重复的头部,并在删除尾部的重复项后决定追加头部和尾部。使 main 函数递归它最终删除所有重复而不更改顺序(并且还保留第一个到来的重复。) 谢谢你,格伦斯。

    【讨论】:

    • 作为一个小改进,您可以先删除尾部的重复项,然后再检查头部是否已经存在。虽然这将保留每个元素的最后一次出现而不是第一次出现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2021-07-01
    相关资源
    最近更新 更多