我正在尝试将列表的最后一个元素放在列表的前面,同时将其余元素按相同的顺序保持N次。我可以用这个函数做一次,但我想在函数中添加另一个参数,以便函数调用N次。
代码:
fun multcshift(L, n) =
if null L then nil
else multcshift(hd(rev L)::(rev(tl(rev L))));
由于
答案 0 :(得分:2)
要使参数 n 有效,您需要递归。你需要一个基本案例,此时函数不再调用自身,并且需要一个递归的情况。对于这个函数,一个很好的基本情况是 n = 0 ,意思是“将前面的最后一个字母移动0次”,即返回 L 而不进行修改。
fun multcshift(L, n) =
if n = 0
then L
else multcshift( hd(rev L)::rev(tl(rev L)) , n - 1 )
此功能的运行时间非常糟糕:对于每个 n ,将列表反转三次!
您可以通过两次调用rev L
来保存至少其中一个列表撤消。 E.g。
fun multcshift (L, 0) = L
| multcshift (L, n) =
let val revL = rev L
in multcshift ( hd revL :: rev (tl revL) , n - 1 ) end
那些hd revL
和rev (tl revL)
似乎是有用的库函数。将函数应用于自己的输出 n 次的过程看起来也是一个很好的库函数。
(* Return all the elements of a non-empty list except the last one. *)
fun init [] = raise Empty
| init ([_]) = []
| init (x::xs) = x::init xs
(* Return the last element of a non-empty list. *)
val last = List.last
(* Shift the last element of a non-empty list to the front of the list *)
fun cshift L = last L :: init L
(* Compose f with itself n times *)
fun iterate f 0 = (fn x => x)
| iterate f 1 = f
| iterate f n = f o iterate f (n-1)
fun multcshift (L, n) = iterate cshift n L
但是运行时间同样糟糕:对于每个 n ,每次都要调用last
和init
。它们都是 O(| L |),就像rev
一样。
您可以通过一次执行多个班次来克服这种复杂性。如果你知道你将移动一个元素 n 次,你也可以转移 n 元素。移动 n 元素相当于删除 | L | - n 来自列表前面的元素,并将它们附加在后面。
但是如果你被要求转移 n 元素 n> | L | ?然后len - n
为否定,List.drop
和List.take
都将失败。您可以通过断定 | L | 元素的任何完全移位对结果没有影响并且 n(mod | L |)就足够了。如果 n< 0
fun multcshift ([], _) = raise Empty
| multcshift (L, 0) = L
| multcshift (L, n) =
let val len = List.length L
in List.drop (L, len - n mod len) @
List.take (L, len - n mod len) end
有很多值得测试的角落案例:
val test_zero = (multcshift ([1,2,3], 0) = [1,2,3])
val test_empty = (multcshift ([], 5); false) handle Empty => true | _ => false
val test_zero_empty = (multcshift ([], 0); false) handle Empty => true | _ => false
val test_negative = (multcshift ([1,2,3,4], ~1) = [2,3,4,1])
val test_nonempty = (multcshift ([1,2,3,4], 3) = [2,3,4,1])
val test_identity = (multcshift ([1,2,3,4], 4) = [1,2,3,4])
val test_large_n = (multcshift [1,2,3,4], 5) = [4,1,2,3])
val test_larger_n = (multcshift [1,2,3,4], 10) = [3,4,1,2])