【问题标题】:Set Intersection with Tail Recursion设置与尾递归的交集
【发布时间】:2014-03-03 10:52:12
【问题描述】:

我正在尝试使用尾递归和空列表[] 作为accu 来生成两组交集的解决方案:

let rec setintersect list list =
  let rec setintersect2 a b c = 
    match a with
      | [] -> (match b with [] -> (setsimplify c) | h::t -> (setsimplify c))
      | h1::t1 -> (match b with [] -> (setsimplify c) |h2::t2 -> (if (elementof h1 b) then (setintersect2 t1 b (c@[h1])) else (setintersect2 t1 b c)))  in
  setintersect2 list list [];;

Elementof 接受“一个 int 和一个列表”,如果 x 是列表的元素,则正确工作以给出 true,否则为 false..

问题来了:

# setintersect [5;2;1] [2;6;9];;
- : int list = [2; 6; 9]

它应该给[2]

我做错了什么? 我觉得我误解了一些非常简单的事情!

编辑: 感谢您迄今为止的回复。

setsimplify 只是删除重复项。 所以[2,2,3,5,6,6] 变成[2,3,5,6]。经过测试并确保其正常工作。

我也不应该使用 List 库中的任何东西。此外,我必须使用“尾递归”,累加器是我在构建时构建的列表。

这是一个想法:

  • 检查list1中的头元素,如果它存在于list2中,则使用“list1的尾部,list2,并列出c并添加该元素” . ELSE,然后使用“list1list2 的尾部并列出 c(原样)”进行递归。

  • 结束条件是list1list2 为空或两者都为空,返回列表c(原样)。

【问题讨论】:

  • 你的setsimplify函数是什么?

标签: recursion ocaml tail-recursion


【解决方案1】:

let rec setintersect list list = 是错误的:这两个参数应该命名不同(你当然应该相应地更新对setintersect2 的调用),否则第二个参数会影响第一个参数。我原以为 OCaml 至少会警告你这个事实,但事实并非如此。

除此之外,代码似乎可以解决问题。不过有几点可以改进:

  • setintersect 本身不是递归的(只有 setintersect2 是),因此您不需要 rec
  • 您应该为setintersect2 的参数找到一个不同的名称。特别是,哪个是累加器并不明显(accaccu 在这些情况下大多数 OCaml 程序员都会理解)。
  • c@[h1] 效率低下:每次追加元素时,您将完全遍历 c。最好做h1::c,最后把结果倒过来
  • 作为奖励,如果你在c的开头追加元素,并假设a是有序的,你不必在调用结束时调用setsimplify:只需检查@是否987654335@ 为空,如果不是这种情况,则仅在不等于 c 的头部时附加 h1

【讨论】:

    【解决方案2】:

    首先,您没有列出您的 setsimplify 函数。

    要编写ocaml 函数,请先尝试拆分,然后尽可能合并。

    要解决这个任务,你只需要遍历l1 中的所有元素,对于每个元素,你检查它是否在l2 中,对吧?

    所以你肯定需要一个函数来检查一个元素是否在列表中,对吧?

    做一个:

    let rec mem x = function
      | [] -> false
      | hd::tl -> hd = x || mem x tl
    

    然后你可以做你的交集:

    let rec inter l1 l2 =
      match l1 with
        | [] -> []
        | hd::tl -> if mem hd l2 then hd::(inter tl l2) else inter tl l2
    

    注意,上面的函数不是尾递归的,我想你可以把它改成尾递归的。


    如果你使用std库,那么很简单:

    let intersection l1 l2 = List.filter (fun x -> List.mem x l2) l1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      相关资源
      最近更新 更多