如何解决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
中。
然后它通过使用 x
或 y
作为第一个元素构建一个新列表,然后递归计算剩余 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 举报,一经查实,本站将立刻删除。