[Python] 2 solutions with explanations
This problem can easily be solved using available functions collections.deque and itertools.combinations. Simply generate all possible combinations and store it
This problem can easily be solved using available functions collections.deque and itertools.combinations. Simply generate all possible combinations and store it in a queue. At each `next()` call `popleft()` from deque and for `hasNext()` check if our queue is not empty. But I don\'t think this solution might be acceptable during interview.\n\n```\nclass CombinationIterator:\n\ndef __init__(self, characters: str, combinationLength: int):\n\tself.dq = deque(combinations(characters, combinationLength))\n\ndef next(self) -> str:\n\treturn \'\'.join(self.dq.popleft())\n\ndef hasNext(self) -> bool:\n\treturn len(self.dq)>0\n```\n\nLet\'s try a different approach and take `characters = \'abcdefg\'` as an example with `combinationLength = 3`. Our first combination then would be \'*abc*\', then it\'s \'*abd*\', \'*abe*\' and so on until we get the last possible combination \'*efg*\'. If we look at indices of our combinations it will be as follows: \'*012*\', \'*013*\', \'*014*\' ... \'*456*\'.\nWe can see that at each step we change index of last character in our combination and move it 1 step further until it reaches the last character. Which would be combination \'*abg*\' = \'*016*\'. Obviously it\'s not the end yet. Once our last character of combination is at the end we take `combination[-2]` character and add 1 to its index. Then we repeat the same process: \'*acd*\'-*023*, \'*ace*\'-*024* ... \'*acg*\'-*026* ... \'*efg*\'-\'*456*\'.  \nWith this approach we do not need to store all possible combinations, just the current one. At each `next()` call we are going to calculate it. \nI\'m storing current combination state in a list of size `combinationLength` and initiate it with `[0,1..n-2]`. For previous example it would look as follows: `[0,1,1]`, so that when we first call `next()` we get the first possible combination `[0,1,2]`.\n`hasNext()` can be checked by comparing `comb[0]` to its last possible position, which is `len(characters) - combinationLength`. \n\n```\nclass CombinationIterator:\n\n    def __init__(self, characters: str, combinationLength: int):\n        self.s = characters\n        self.comb = [i for i in range(combinationLength-1)] + [combinationLength-2]\n        \n    def next(self) -> str:\n        for i in range(1, len(self.comb)+1):\n            if self.comb[-i] < len(self.s)-i:\n                self.comb[-i] += 1\n                while i != 1: \n                    self.comb[-i+1] = self.comb[-i] + 1\n                    i -= 1\n                break\n            \n        return \'\'.join([self.s[pos] for pos in self.comb])\n\n    def hasNext(self) -> bool:\n        return self.comb[0] != len(self.s) - len(self.comb)\n```\n
['Python']