Bird
Raised Fist0
Swiftprogramming~5 mins

Sequence protocol for custom iteration in Swift - Time & Space Complexity

Choose your learning style10 modes available
Time Complexity: Sequence protocol for custom iteration
O(n)
Understanding Time Complexity

When we create a custom sequence in Swift, we want to know how long it takes to go through all its items.

We ask: How does the time to iterate change as the sequence gets bigger?

Scenario Under Consideration

Analyze the time complexity of the following code snippet.


struct CountDown: Sequence {
  let start: Int
  func makeIterator() -> some IteratorProtocol {
    var current = start
    return AnyIterator {
      if current <= 0 { return nil }
      defer { current -= 1 }
      return current
    }
  }
}

This code creates a countdown sequence from a starting number down to 1.

Identify Repeating Operations

Identify the loops, recursion, array traversals that repeat.

  • Primary operation: Each call to the iterator's next() method returns one number.
  • How many times: The iterator runs once for each number from start down to 1.
How Execution Grows With Input

Each step in the countdown takes about the same time, so total time grows as we add more numbers.

Input Size (n)Approx. Operations
1010 steps
100100 steps
10001000 steps

Pattern observation: The time grows directly with the number of items to iterate.

Final Time Complexity

Time Complexity: O(n)

This means the time to go through the sequence grows in a straight line with the number of items.

Common Mistake

[X] Wrong: "The iterator runs faster because it uses a simple countdown."

[OK] Correct: Even simple steps add up, so the total time still grows with the number of items.

Interview Connect

Understanding how iteration time grows helps you explain performance clearly when creating custom sequences.

Self-Check

"What if the iterator returned two numbers per step instead of one? How would the time complexity change?"

Practice

(1/5)
1. What does the Sequence protocol in Swift require you to provide for custom iteration?
easy
A. A property that stores all elements in an array
B. A method named start() that begins the iteration
C. A function that returns the count of elements
D. An iterator with a next() method that returns elements or nil

Solution

  1. Step 1: Understand the Sequence protocol requirement

    The Sequence protocol requires an iterator that can provide elements one by one.
  2. Step 2: Identify the iterator method

    This iterator must have a next() method that returns the next element or nil when done.
  3. Final Answer:

    An iterator with a next() method that returns elements or nil -> Option D
  4. Quick Check:

    Sequence needs next() iterator method = C [OK]
Hint: Sequence needs an iterator with next() returning nil at end [OK]
Common Mistakes:
  • Thinking Sequence requires a start() method
  • Assuming all elements must be stored in an array
  • Confusing count with iteration method
2. Which of the following is the correct way to declare a custom iterator type conforming to IteratorProtocol in Swift?
easy
A. struct MyIterator: IteratorProtocol { func next() -> Int { return 0 } }
B. class MyIterator { func next() -> Int { return 0 } }
C. struct MyIterator: Sequence { func next() -> Int? { return nil } }
D. struct MyIterator: IteratorProtocol { func next() -> Int? { return nil } }

Solution

  1. Step 1: Check protocol conformance and method signature

    IteratorProtocol requires a next() method returning an optional element type, here Int?.
  2. Step 2: Validate each option

    struct MyIterator: IteratorProtocol { func next() -> Int? { return nil } } correctly declares a struct conforming to IteratorProtocol with next() -> Int?. class MyIterator { func next() -> Int { return 0 } } lacks conformance and returns non-optional. struct MyIterator: Sequence { func next() -> Int? { return nil } } wrongly conforms to Sequence, not IteratorProtocol. struct MyIterator: IteratorProtocol { func next() -> Int { return 0 } } returns non-optional Int, which is incorrect.
  3. Final Answer:

    struct MyIterator: IteratorProtocol { func next() -> Int? { return nil } } -> Option A
  4. Quick Check:

    IteratorProtocol requires next() returning optional = D [OK]
Hint: IteratorProtocol's next() must return optional element type [OK]
Common Mistakes:
  • Returning non-optional from next()
  • Confusing Sequence with IteratorProtocol
  • Missing protocol conformance declaration
3. Consider this Swift code implementing a custom sequence:
struct CountDown: Sequence {
  let start: Int
  func makeIterator() -> some IteratorProtocol {
    var current = start
    return AnyIterator {
      if current <= 0 { return nil }
      defer { current -= 1 }
      return current
    }
  }
}

for number in CountDown(start: 3) {
  print(number)
}
What is the output?
medium
A. 3 2 1 0
B. 3 2 1
C. 4 3 2 1
D. 1 2 3

Solution

  1. Step 1: Understand the iterator logic

    The iterator starts at start (3). It returns current if > 0, then decreases current by 1 after returning.
  2. Step 2: Trace the iteration values

    First call returns 3, then current becomes 2. Next returns 2, current becomes 1. Next returns 1, current becomes 0. Next call returns nil because current is 0, ending iteration.
  3. Final Answer:

    3 2 1 -> Option B
  4. Quick Check:

    CountDown from 3 to 1 = 3 2 1 [OK]
Hint: Check when next() returns nil to find iteration end [OK]
Common Mistakes:
  • Including 0 in output though iteration stops before
  • Assuming count goes up instead of down
  • Misreading defer behavior
4. This code attempts to create a custom sequence but has an error:
struct MySequence: Sequence {
  func makeIterator() -> MyIterator {
    return MyIterator()
  }
}

struct MyIterator: IteratorProtocol {
  var count = 3
  func next() -> Int? {
    if count == 0 { return nil }
    count -= 1
    return count
  }
}
What is the main problem here?
medium
A. next() is a func but modifies count, which is a struct property
B. makeIterator() should return IteratorProtocol instead of MyIterator
C. count should start at 0, not 3
D. next() must return non-optional Int

Solution

  1. Step 1: Identify mutability issue in next()

    The next() method tries to change count, but it is declared in a struct and next() is not marked mutating.
  2. Step 2: Understand Swift struct rules

    In structs, methods that modify properties must be marked mutating. Without it, the compiler will error.
  3. Final Answer:

    next() is a func but modifies count, which is a struct property -> Option A
  4. Quick Check:

    Mutating methods must be marked mutating = A [OK]
Hint: Mark methods mutating if they change struct properties [OK]
Common Mistakes:
  • Forgetting mutating keyword on next()
  • Thinking return type must be non-optional
  • Confusing return type with protocol requirement
5. You want to create a custom sequence that iterates over only even numbers from 2 up to a given limit. Which implementation correctly uses the Sequence protocol for this?
hard
A. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { while current <= limit { let result = current current += 2 return result } return nil } } }
B. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 0 return AnyIterator { current += 2 if current < limit { return current } return nil } } }
C. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { if current <= limit { let result = current current += 2 return result } return nil } } }
D. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 0 return AnyIterator { if current < limit { current += 2 return current } return nil } } }

Solution

  1. Step 1: Check iterator logic for even numbers

    The iterator should start at 2 and return current if <= limit, then add 2 for next call.
  2. Step 2: Analyze each option's iteration behavior

    struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { while current <= limit { let result = current current += 2 return result } return nil } } } uses a while loop inside the closure, which causes it to return only once and then exit, so it won't iterate properly. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { if current <= limit { let result = current current += 2 return result } return nil } } } uses an if check and returns current then increments, correctly producing even numbers up to limit. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 0 return AnyIterator { current += 2 if current < limit { return current } return nil } } } increments before checking, so first returned number is 2, which is correct, but starts at 0 which is okay. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 0 return AnyIterator { if current < limit { current += 2 return current } return nil } } } increments after checking current < limit, so it may skip the limit if limit is even. struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { if current <= limit { let result = current current += 2 return result } return nil } } } is the clearest and correct implementation.
  3. Final Answer:

    struct EvenNumbers: Sequence { let limit: Int func makeIterator() -> AnyIterator<Int> { var current = 2 return AnyIterator { if current <= limit { let result = current current += 2 return result } return nil } } } -> Option C
  4. Quick Check:

    Use if check and increment after return for correct iteration = B [OK]
Hint: Use if condition inside iterator closure, not while loop [OK]
Common Mistakes:
  • Using while loop inside iterator closure causing single return
  • Incrementing before returning causing off-by-one errors
  • Incorrect start value causing wrong first element
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard