Approach
Depth-first search
For Iterator for Combination, the implementation follows one branch at a time, making it suitable for components, trees, backtracking, or dependency exploration.
- Define the state carried into one recursive or stack frame.
- Mark or choose the current state before exploring children.
- Combine child results or undo the choice when the branch finishes.
Code notes
- 94 lines of Python from the credited upstream file iterator-for-combination.py.
- The implementation visibly relies on sequence storage.
- No explicit loop blocks detected.
Complexity
Count unique states for graph traversal; for backtracking, count the branching factor and maximum depth.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 4import itertools5 6 7class CombinationIterator(object):8 9 def __init__(self, characters, combinationLength):10 """11 :type characters: str12 :type combinationLength: int13 """14 self.__it = itertools.combinations(characters, combinationLength)15 self.__curr = None16 self.__last = characters[-combinationLength:]17 18 def next(self):19 """20 :rtype: str21 """22 self.__curr = "".join(self.__it.next())23 return self.__curr24 25 def hasNext(self):26 """27 :rtype: bool28 """29 return self.__curr != self.__last30 31 323334import functools35 36 37class CombinationIterator2(object):38 39 def __init__(self, characters, combinationLength):40 """41 :type characters: str42 :type combinationLength: int43 """44 self.__characters = characters45 self.__combinationLength = combinationLength46 self.__it = self.__iterative_backtracking()47 self.__curr = None48 self.__last = characters[-combinationLength:]49 50 def __iterative_backtracking(self):51 def conquer():52 if len(curr) == self.__combinationLength:53 return curr54 55 def prev_divide(c):56 curr.append(c)57 58 def divide(i):59 if len(curr) != self.__combinationLength:60 for j in reversed(xrange(i, len(self.__characters)-(self.__combinationLength-len(curr)-1))):61 stk.append(functools.partial(post_divide))62 stk.append(functools.partial(divide, j+1))63 stk.append(functools.partial(prev_divide, self.__characters[j]))64 stk.append(functools.partial(conquer))65 66 def post_divide():67 curr.pop()68 69 curr = []70 stk = [functools.partial(divide, 0)]71 while stk:72 result = stk.pop()()73 if result is not None:74 yield result75 76 def next(self):77 """78 :rtype: str79 """80 self.__curr = "".join(next(self.__it))81 return self.__curr82 83 def hasNext(self):84 """85 :rtype: bool86 """87 return self.__curr != self.__last88 89 9091929394