微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

F# 中的递归函数,在 n 个 int 类型元素的列表中确定两个相邻值中的较大值

如何解决F# 中的递归函数,在 n 个 int 类型元素的列表中确定两个相邻值中的较大值

我最近开始学习 f#,但我在执行主题行中的任务时遇到了问题。我设法解决了这个任务,但没有使用递归函数。我试图将我的函数转换为递归函数,但它不起作用,因为在函数中我创建了数组,然后我更改了哪些元素。请告诉我如何将我的函数转换为递归函数或如何执行此任务。

let list = [8;4;3;3;5;9;-7]
let comp (a,b) = if a>b then a elif b = a then a else b  
let maks (b: _ list)  =
    let x = b.Length
    if x % 2 = 0 then
        let tab = Array.create ((x/2)) 0
        for i = 0 to (x/2)-1 do
            tab.[i] <- (comp(b.Item(2*i),b.Item(2*i+1))) 
        let newlist = tab |> Array.toList 
        newlist
    else
        let tab = Array.create (((x-1)/2)+1) 0
        tab.[(((x-1)/2))] <- b.Item(x-1)
        for i = 0 to ((x-1)/2)-1 do
            tab.[i] <- (comp(b.Item(2*i),b.Item(2*i+1)))
        let newlist = tab |> Array.toList 
        newlist

解决方法

如果这是一个家庭作业问题,我不想给出答案,所以请考虑这个伪代码解决方案:

  • 如果列表至少包含两个元素:
    • 回答包含以下内容的新列表:
      • 前两个元素中较大的一个,后跟
      • 递归地将函数应用到列表的其余部分
  • 否则列表包含少于两个元素:
    • 回答列表不变

提示:F# 的 pattern matching 能力使其易于实现。

,

值得注意的是,如果您这样做不是为了学习目的,那么使用 chunkBySize 函数有一个很好的方法:

list 
|> List.chunkBySize 2
|> List.map (fun l -> comp(l.[0],l.[l.Length-1]))

这会将列表分成大小最多为 2 的块。对于每个块,您可以将第一个元素与最后一个元素进行比较,这就是您想要的结果。

,

在您的指导下,我设法创建了以下功能:

let rec maks2 (b: _ list,newlist: _ list,i:int) =
let x = b.Length
if x >= 2 then
    if x % 2 = 0 then
        if i < ((x/2)-1)+1 then
            let d = (porownaj(b.Item(2*i),b.Item(2*i+1))) 
            let list2 = d::newlist
            maks2(b,list2,i+1)
        else
        newlist
    else
        if i < ((x/2)-1)+1 then
            let d = (porownaj(b.Item(2*i),i+1)
        else
        let list3 = b.Item(x-1)::newlist
        list3
else
    b

该函数正常工作,它接受列表、空列表和索引作为参数。 唯一的问题是返回的列表是反向的,即应该在末尾的值在开头。如何将项目添加到列表的末尾?

,

您可以在一个步骤中使用模式匹配来匹配和检查/提取列表。典型的递归函数如下所示:

let rec adjGreater xs =
    match xs with
    | []         -> []
    | [x]        -> [x]
    | x::y::rest -> (if x >= y then x else y) :: adjGreater rest

它检查列表是空的,有一个元素,还是有两个元素,剩下的列表在 rest 中。

然后它通过使用 xy 作为第一个元素构建一个新列表,然后递归计算剩余 rest 的结果。

这不是尾递归。尾调用优化版本将是,而不是使用递归调用的结果。您将创建一个新列表,并将到目前为止的计算值传递给递归函数。通常这种方式,你想创建一个内部递归循环函数。

由于您只能将值添加到列表的顶部,因此您需要像这样反转递归函数的结果:

let adjGreater xs =
    let rec loop xs result =
        match xs with
        | []         -> result
        | [x]        -> x :: result
        | x::y::rest -> loop rest ((if x >= y then x else y) :: result)
    List.rev (loop xs [])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?