ここに1つのインタビューの質問があります:
与えられた数の同じ桁で形成できる次に大きい数を見つけます。
入力:4765、出力:5467
を使用する場合array
、それはそれほど難しいことではありません。
- 数値を桁配列に変換します。
x
配列をスキャンし、次の隣人が大きい最新の(最も低い位置)桁(たとえば)を記録します- 次のネイバーが小さい場合(つまり、降順である場合)、xよりも大きい最小の桁を記録します(たとえば、
y
) - 最後に、xとyを交換します
しかし、OCamlでは、を使用するlist
と、その方法がわかりません。アルゴリズムが再帰を難しくしているようです。
助言がありますか?
編集:
機能的な方法を希望していることに注意してください(リストを使用)
編集
@comingstormのアドバイスに従うことで、私は次のように実装しました。
exception NotFound;;
let rev_list_of_int n =
let rec process n =
let x = n / 10 and y = n mod 10
in
if x = 0 && y = 0 then []
else
y::(process x)
in
process n;;
let find_next_by_list n =
let l = rev_list_of_int n
in
let rec find_x before_x x after_x =
match after_x with
| [] | _::[] -> (before_x, -1, after_x)
| hd1::hd2::tl ->
if hd1 > hd2 then (hd1::before_x, hd2, tl)
else find_x (hd1::before_x) x (hd2::tl)
in
let (bx, x, ax) = find_x [] (-1) l (* ax is rev *)
in
if x = -1 then raise NotFound
else
let rec find_y x path = function
| [] -> raise NotFound
| hd::tl ->
if hd > x then (path, hd, tl)
else find_y x (hd::path) tl
in
let (left, y, right) = find_y x [] (List.rev bx) (* left is rev, right is not *)
in
(* rev ax, then y, then right, then x, then rev left*)
(List.rev_append (y::ax) right) @ (x::List.rev left)