3

我正在尝试在函数中输入一个列表,它会向我发送一个列表,其中包含使用 f# 和以下递归删除的前半部分元素,但我一直遇到一个我无法弄清楚的基本情况问题。有什么想法吗?我正在使用第二个影子列表来计算我需要走多远,直到我进入列表的一半(通过一次删除两个元素)

let rec dropHalf listToDrop shadowList = 
    match shadowList with
    | [] -> listToDrop
    | shadowHead2::shadowHead1::shadowTail -> if shadowTail.Length<=1 then listToDrop else 
                                    match listToDrop with 
                                    |[] -> listToDrop
                                    |listToDropHead::listToDropTail -> dropHalf listToDropTail shadowTail
4

4 回答 4

2
let rec dropHalf listToDrop shadowList = 
    match shadowList with
    | [] -> listToDrop
    | shadowHead2::[] -> listToDrop   (* odd number! *)
    | shadowHead1::shadowHead2::shadowTail -> 
        match listToDrop with 
        | [] -> listToDrop   (* should never happen? *)
        | listToDropHead::listToDropTail -> dropHalf listToDropTail shadowTail

恐怕我不使用 F#,但它类似于 ocaml,所以希望以下内容接近您正在寻找的内容(也许评论格式已更改?!)。这个想法是,当你耗尽阴影时,你就完成了。您的代码几乎就在那里,但影子尾巴上的长度测试毫无意义。

我想强调的是,这不像任何人都会写“在现实生活中”,但听起来你正在与一些奇怪的要求作斗争。

于 2012-05-22T01:31:26.053 回答
1

因为您使用与原始列表长度相同的影子列表,并以不同的速率从这些列表中删除元素,所以最好创建一个辅助函数:

let dropHalf xs =
    let rec dropHalf' ys zs =
      match ys, zs with
      | _::_::ys', _::zs' -> dropHalf' ys' zs'
      | _, zs' -> zs' (* One half of the shadow list ys *)
    dropHalf' xs xs

如果您不想遍历列表两次,则以下解决方案更简单:

let rec drop n xs =
   match xs, n with
   | _ when n < 0 -> failwith "n should be greater or equals to 0"
   | [], _ -> []
   | _, 0 -> xs
   | _::xs', _ -> drop (n-1) xs'

let dropHalf xs =
    xs |> drop (List.length xs/2)

另一个简单的解决方案需要一些额外的空间,但不必使用递归:

let dropHalf xs = 
    let xa = Array.ofList xs
    xa.[xa.Length/2..] |> List.ofArray
于 2012-05-22T02:13:48.473 回答
1

作为一般的经验法则,如果您正在调用Length列表,那么很可能有更好的方法来做您正在做的事情。 Length必须迭代整个列表,因此是 O(n)。

let secondHalf list =
    let rec half (result : 'a list) = function
        | a::b::sx -> half result.Tail sx
        // uncomment to remove odd value from second half
        // | (a::sx) -> result.Tail 
        | _ -> result

    half list list
于 2012-05-22T16:29:38.153 回答
0

这是您所描述的示例。

open System
open System.Collections.Generic

let items = seq { 1 .. 100 } |> Seq.toList

let getBackOfList ( targetList : int list) = 
    if (targetList.Length = 0) then 
        targetList
    else
        let len = targetList.Length
        let halfLen = len / 2
        targetList |> Seq.skip halfLen |> Seq.toList

let shortList = items |> getBackOfList

("Len: {0}", shortList.Length) |> Console.WriteLine

let result = Console.ReadLine() 

希望这可以帮助

于 2012-05-22T01:31:38.453 回答