Let be the number of leaves; the total number of nodes is . List concatenation copies its left operand. For a tree whose left subtree contains leaves at each successive internal node, these copied lengths are . Their sum is , so the worst-case running time is .
A difference list representation avoids copying prefixes:
flattenFast :: Tree a -> [a]
flattenFast t = go t []
where
go (One x) acc = x:acc
go (Two l r) acc = go l (go r acc)The recursion invariant is
go t acc = flatten t ++ acc. The leaf case is immediate; the internal-node case uses associativity of list concatenation. Each node is visited once and each leaf contributes one output constructor, giving running time when the result is fully consumed. This is linear flattening of a binary tree and does not assume balance.Assume the subtrees rooted at the children in a rooted tree of already obey the max-heap condition. Compare with each present child and choose an index of the largest of these at most three keys. If that index is , stop. Otherwise exchange the two keys, continue at the chosen child, and repeat. This is sift down, with the inequality reversed from a minimum-oriented binary heap.
The exchange repairs the old root position because its new key dominates both child roots; only the subtree receiving the displaced key can still be defective. This recursion invariant proves correctness. Each exchange descends one level and costs constant work, so the worst-case running time is for subtree height , hence . A small key at the root of a suitably ordered heap must descend to a leaf, so the logarithmic worst-case bound is attained.
Change the right fold's result type to an accumulator-transforming function type:Thus
foldlAsFoldr :: (b -> a -> b) -> b -> [a] -> b
foldlAsFoldr s n xs = foldr c id xs n
where
c x k a = k (s a x)c x k = \a -> k (s a x) and k = id in the question's notation. Here c :: a -> (b -> b) -> (b -> b), and the fold's base value is the identity function, not the initial accumulator n.The recursion invariant is At an undefined spine, applying the undefined folded function also gives the bottom value. The finite-approximation argument then covers infinite lazy lists. This is a continuation representation of a left fold: the result retains the operation still to be performed, avoiding the information loss in part (d).
foldr c id xs a = foldl s a xs for every a. For [], both sides equal a. For a cons:foldr c id (x:xs) a
= c x (foldr c id xs) a
= foldr c id xs (s a x)
= foldl s (s a x) xs
= foldl s a (x:xs).To preserve the actual printed function, including its handling of nonpositive exponents and wrapping
Int bases, use a tail-recursive accumulator with the same multiplication order:def anotherfuncRec(x: Int, n: Long): Double = {
require(x > 0)
@scala.annotation.tailrec
def loop(y: Int, i: Long, result: Double): Double = {
if (i <= 0) result
else {
val nextResult = if (i % 2 == 1) result * y else result
loop(y * y, i / 2, nextResult)
}
}
loop(x, n, 1.0)
}Each recursive call corresponds to one source iteration and carries exactly its next program state. Hence it reproduces the printed numerical behavior, rather than silently repairing it. For positive
n, both routines use steps; for nonpositive n, both take constant time. The recursive call is in tail position, so Scala's tail-call optimization avoids a growing call stack; the annotation asks the compiler to check that condition.If the intended exact power is required instead, change the base and accumulator parameters of this same recurrence to
BigInt and require n >= 0, as in part (d). Its mathematical loop invariant becomes a recursion invariant, with the same logarithmic number of multiplication steps. Recursion invariant 2026-10-24
A relationship between a recursive procedure's arguments, accumulated state and original input that holds at every reachable recursive call. For accumulator-based exponentiation by squaring, is a recursion invariant under exact arithmetic. The base case converts it into the desired result, while the recursive step and a decreasing argument justify preservation and termination.