Design and implement a data structure for a compressed string iterator. The given compressed string will be in the form of each letter followed by a positive integer representing the number of this letter existing in the original uncompressed string.
Implement the StringIterator class:
next() Returns the next character if the original string still has uncompressed characters, otherwise returns a white space.
hasNext() Returns true if there is any letter needs to be uncompressed in the original string, otherwise returns false.
compressedString consists of lower-case an upper-case English letters and digits.
The number of a single character repetitions in compressedString is in the range [1, 10^9]
At most 100 calls will be made to next and hasNext.
Solutions
Solution 1: Parsing and Storing
Parse the compressedString into characters \(c\) and their corresponding repetition counts \(x\), and store them in an array or list \(d\). Use \(p\) to point to the current character.
Then perform operations in next and hasNext.
The initialization time complexity is \(O(n)\), and the time complexity of the other operations is \(O(1)\). Here, \(n\) is the length of compressedString.
classStringIterator:def__init__(self,compressedString:str):self.d=[]self.p=0n=len(compressedString)i=0whilei<n:c=compressedString[i]x=0i+=1whilei<nandcompressedString[i].isdigit():x=x*10+int(compressedString[i])i+=1self.d.append([c,x])defnext(self)->str:ifnotself.hasNext():return' 'ans=self.d[self.p][0]self.d[self.p][1]-=1ifself.d[self.p][1]==0:self.p+=1returnansdefhasNext(self)->bool:returnself.p<len(self.d)andself.d[self.p][1]>0# Your StringIterator object will be instantiated and called as such:# obj = StringIterator(compressedString)# param_1 = obj.next()# param_2 = obj.hasNext()
classStringIterator{privateList<Node>d=newArrayList<>();privateintp;publicStringIterator(StringcompressedString){intn=compressedString.length();inti=0;while(i<n){charc=compressedString.charAt(i);intx=0;while(++i<n&&Character.isDigit(compressedString.charAt(i))){x=x*10+(compressedString.charAt(i)-'0');}d.add(newNode(c,x));}}publiccharnext(){if(!hasNext()){return' ';}charans=d.get(p).c;if(--d.get(p).x==0){++p;}returnans;}publicbooleanhasNext(){returnp<d.size()&&d.get(p).x>0;}}classNode{charc;intx;Node(charc,intx){this.c=c;this.x=x;}}/** * Your StringIterator object will be instantiated and called as such: * StringIterator obj = new StringIterator(compressedString); * char param_1 = obj.next(); * boolean param_2 = obj.hasNext(); */
classStringIterator{public:StringIterator(stringcompressedString){intn=compressedString.size();inti=0;while(i<n){charc=compressedString[i];intx=0;while(++i<n&&isdigit(compressedString[i])){x=x*10+(compressedString[i]-'0');}d.push_back({c,x});}}charnext(){if(!hasNext())return' ';charans=d[p].first;if(--d[p].second==0){++p;}returnans;}boolhasNext(){returnp<d.size()&&d[p].second>0;}private:vector<pair<char,int>>d;intp=0;};/** * Your StringIterator object will be instantiated and called as such: * StringIterator* obj = new StringIterator(compressedString); * char param_1 = obj->next(); * bool param_2 = obj->hasNext(); */
typepairstruct{cbytexint}typeStringIteratorstruct{d[]pairpint}funcConstructor(compressedStringstring)StringIterator{n:=len(compressedString)i:=0d:=[]pair{}fori<n{c:=compressedString[i]x:=0i++fori<n&&compressedString[i]>='0'&&compressedString[i]<='9'{x=x*10+int(compressedString[i]-'0')i++}d=append(d,pair{c,x})}returnStringIterator{d,0}}func(this*StringIterator)Next()byte{if!this.HasNext(){return' '}ans:=this.d[this.p].cthis.d[this.p].x--ifthis.d[this.p].x==0{this.p++}returnans}func(this*StringIterator)HasNext()bool{returnthis.p<len(this.d)&&this.d[this.p].x>0}/** * Your StringIterator object will be instantiated and called as such: * obj := Constructor(compressedString); * param_1 := obj.Next(); * param_2 := obj.HasNext(); */
classStringIterator{privated:[string,number][]=[];privatep:number=0;constructor(compressedString:string){constn=compressedString.length;leti=0;while(i<n){constc=compressedString[i];letx=0;i++;while(i<n&&!isNaN(Number(compressedString[i]))){x=x*10+Number(compressedString[i]);i++;}this.d.push([c,x]);}}next():string{if(!this.hasNext()){return' ';}constans=this.d[this.p][0];this.d[this.p][1]--;if(this.d[this.p][1]===0){this.p++;}returnans;}hasNext():boolean{returnthis.p<this.d.length&&this.d[this.p][1]>0;}}/** * Your StringIterator object will be instantiated and called as such: * var obj = new StringIterator(compressedString) * var param_1 = obj.next() * var param_2 = obj.hasNext() */