2

私はこの問題を解決しようとしています

演習 8.3 数値のリストを受け取り、累積和を返す関数を書きなさい。つまり、i 番目の要素が元のリストの最初の i + 1 要素の合計である新しいリストです。たとえば、[1, 2, 3] の累積和は [1, 3, 6] です。

私はこのコードを書きましたが、これは私にとって正しいものです。

let lastItem = function 
  | [] -> 0
  | l -> List.hd (List.rev l);;

let rec cumulativeSumActual accum input =
match input with
  | [] -> accum
  | hd::tl -> cumulativeSumActual (accum::[(lastItem accum) + hd]) tl;;

let cumulativeSum = cumulativeSumActual [];;

let output = cumulativeSum [1; 2; 3;];;

let printer item =
    print_int item
    print_string "\n";;

List.iter printer output

しかし、私はエラーが発生します

user1@ubuntu:~/Documents/Programs$ ocamlc -o CumulativeList CumulativeList.ml
File "CumulativeList.ml", line 8, characters 33-38:
Error: This expression has type 'a list
       but an expression was expected of type 'a

次に、コードを次のように変更しました

  | hd::tl -> cumulativeSumActual (accum@[(lastItem accum) + hd]) tl;;

そしてそれは働いた!

しかし、cons 演算子が機能しなかった理由と、新しいリストの追加操作が機能した理由がわかりません。

cons 演算子は、単純に新しい項目をリストに追加し、新しいリストを再帰呼び出しの最初のパラメーターとして返す必要がありますか?

どうしたの?

4

2 に答える 2

1

まずcon、先頭のリストに要素をプッシュします。たとえば、12::[13,1,3]. con (::)リストをリストにすることはできません。あなたのコードでは、明らかにaccum'a listであり、 ではありません'a。あなたのコード(accum::[(lastItem accum) + hd])は 2 つのリストを試してconいますよね?

2つ目@は、 2 つのリストを接続する です。これが|appendの理由です。hd::tl ->cumulativeSumActual (accum@[(lastItem accum) + hd]) tl;; 正しい。

第三に、私は解決策を

let c_sum l =
  let rec sum pre acc = function
    | [] -> acc
    | hd::tl -> let tmp_sum = pre+hd in sum tmp_sum (tmp_sum::acc) tl
  in sum 0 [] l

PS、2 つのリストを接続しようとするときは注意が必要です。通常、この操作には 1 つのリストを走査する必要があるため、O(n) が必要です。

于 2013-09-09T09:21:48.450 に答える