Here is one interview question:
find the next greatest number that can be form by same digit of the given number ..
input: 4765, output: 5467
If using array
, it is not that hard.
- we transform the number to digit array.
- we scan the array, record the latest (lowest position) digit (say as
x
) whose next neighbor is bigger - if the next neighbor is smaller (which means it is descending), then we record the smallest digit that bigger than x (say as
y
) - finally, we exchange x and y
However, in OCaml, if we use list
, then I don't know how to do it. It seems the algorithm makes recursive hard.
Any suggestions?
Edit:
Please note I wish for a functional way (using list)
Edit
by follow @comingstorm's advices, I implemented like this:
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)
option
instead... – comingstorm