Recursive enumerations in Swift - Time & Space Complexity
When using recursive enumerations, it is important to understand how the number of steps grows as the data structure gets bigger.
We want to know how the time to process these recursive values changes with their size.
Analyze the time complexity of the following code snippet.
indirect enum List {
case end
case node(Int, List)
}
func length(_ list: List) -> Int {
switch list {
case .end:
return 0
case let .node(_, tail):
return 1 + length(tail)
}
}
This code defines a recursive list and a function to count how many elements it has.
- Primary operation: Recursive calls to
lengthfor each node in the list. - How many times: Once for every element until the end of the list is reached.
Each element in the list causes one recursive call, so the work grows directly with the number of elements.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 calls |
| 100 | 100 calls |
| 1000 | 1000 calls |
Pattern observation: The number of steps grows in a straight line with the size of the list.
Time Complexity: O(n)
This means the time to count elements grows directly in proportion to the number of elements.
[X] Wrong: "Recursive enumerations always cause exponential time because of recursion."
[OK] Correct: Here, each recursive call processes one element only once, so the time grows linearly, not exponentially.
Understanding how recursion works with data structures like recursive enums helps you explain and reason about code clearly in interviews.
"What if the list was a tree with two recursive branches instead of one? How would the time complexity change?"
Practice
indirect keyword do in a Swift recursive enumeration?Solution
Step 1: Understand the role of
Theindirectindirectkeyword tells Swift that the enum cases can hold references to the enum itself, enabling recursion.Step 2: Identify what recursion means in enums
Recursion means an enum case can contain another instance of the same enum, which requiresindirectto avoid infinite size.Final Answer:
It allows the enum to refer to itself recursively. -> Option AQuick Check:
indirectenables recursion = C [OK]
- Thinking indirect makes enum immutable
- Confusing indirect with class conversion
- Believing indirect disables switch usage
Solution
Step 1: Recall how to declare recursive enums
Swift allows marking the whole enum asindirectto enable recursion for all cases.Step 2: Check each option's syntax
The syntaxindirect enum Tree { case leaf(Int); case node(Tree, Tree) }correctly enables recursion by marking the whole enum indirect. Other options either lack the keyword, apply it only to non-recursive cases (leaving recursive case without), or contain syntax errors such as missing thecasekeyword.Final Answer:
indirect enum Tree { case leaf(Int); case node(Tree, Tree) } -> Option DQuick Check:
Whole enum indirect = A [OK]
- Omitting indirect keyword
- Placing indirect only on some cases incorrectly
- Using indirect outside enum declaration
print(tree.countLeaves())?
indirect enum Tree {
case leaf(Int)
case node(Tree, Tree)
func countLeaves() -> Int {
switch self {
case .leaf(_): return 1
case let .node(left, right):
return left.countLeaves() + right.countLeaves()
}
}
}
let tree = Tree.node(.leaf(1), Tree.node(.leaf(2), .leaf(3)))Solution
Step 1: Understand the tree structure
The tree is: node(leaf(1), node(leaf(2), leaf(3))). It has three leaves: 1, 2, and 3.Step 2: Count leaves recursively
The countLeaves function returns 1 for each leaf and sums counts for nodes. So total leaves = 1 + (1 + 1) = 3.Final Answer:
3 -> Option CQuick Check:
Leaves counted = 3 [OK]
- Counting nodes instead of leaves
- Misunderstanding recursive calls
- Forgetting to sum both sides
enum List {
case end
case node(Int, List)
}Solution
Step 1: Check for recursion support
The enum List has a casenode(Int, List)which refers to itself, so it is recursive.Step 2: Verify use of
Swift requires marking recursive enums or cases withindirectindirect. This enum lacks it, causing a compile error.Final Answer:
Missingindirectkeyword for recursion. -> Option AQuick Check:
Recursive enum needs indirect = B [OK]
- Ignoring indirect keyword requirement
- Thinking recursion needs classes
- Assuming all enum cases need associated values
indirect enum Tree {
case leaf(Int)
case node(Tree, Tree)
func depth() -> Int {
// Your code here
}
}Solution
Step 1: Define depth for leaf nodes
Leaves have depth 0 because they have no children.Step 2: Define depth for node cases
Nodes have depth 1 plus the maximum depth of their two child trees.Final Answer:
Return 0 for leaf, and 1 + max depth of left and right nodes. -> Option BQuick Check:
Depth = 0 for leaf, max + 1 for node = A [OK]
- Using sum instead of max for node depth
- Returning 1 for leaf depth incorrectly
- Using min instead of max for node depth
Ready to prove it?
Pass the test and this pattern moves unknown
