604. Design Compressed String Iterator
leetcode easy
Task
Разработайте и реализуйте структуру данных для итератора сжатой строки. Данная сжатая строка будет в виде каждой буквы, за которой следует положительное целое число, представляющее количество этой буквы в оригинальной несжатой строке.
Реализуйте класс
StringIterator
-
next()
: Возвращает следующий символ, если в оригинальной строке еще остались несжатые символы, в противном случае возвращает пробел.
-
hasNext()
: Возвращает
true
, если в оригинальной строке остались символы, которые нужно распаковать, в противном случае возвращает
false
.
Пример:
Input
["StringIterator", "next", "next", "next", "next", "next", "next", "hasNext", "next", "hasNext"]
[["L1e2t1C1o1d1e1"], [], [], [], [], [], [], [], [], []]
Output
[null, "L", "e", "e", "t", "C", "o", true, "d", true]
Explanation
StringIterator stringIterator = new StringIterator("L1e2t1C1o1d1e1");
stringIterator.next(); // return "L"
stringIterator.next(); // return "e"
stringIterator.next(); // return "e"
stringIterator.next(); // return "t"
stringIterator.next(); // return "C"
stringIterator.next(); // return "o"
stringIterator.hasNext(); // return True
stringIterator.next(); // return "d"
stringIterator.hasNext(); // return True
C# solution
matched/originalpublic class StringIterator {
private StringBuilder res = new StringBuilder();
private int ptr = 0;
public StringIterator(string s) {
int i = 0;
while (i < s.Length) {
char ch = s[i++];
int num = 0;
while (i < s.Length && char.IsDigit(s[i])) {
num = num * 10 + (s[i] - '0');
i++;
}
for (int j = 0; j < num; j++)
res.Append(ch);
}
}
public char Next() {
return !HasNext() ? ' ' : res[ptr++];
}
public bool HasNext() {
return ptr != res.Length;
}
}C++ solution
auto-draft, review before submit#include <bits/stdc++.h>
using namespace std;
// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class StringIterator {
private StringBuilder res = new StringBuilder();
private int ptr = 0;
public StringIterator(string s) {
int i = 0;
while (i < s.size()) {
char ch = s[i++];
int num = 0;
while (i < s.size() && char.IsDigit(s[i])) {
num = num * 10 + (s[i] - '0');
i++;
}
for (int j = 0; j < num; j++)
res.Append(ch);
}
}
public char Next() {
return !HasNext() ? ' ' : res[ptr++];
}
public bool HasNext() {
return ptr != res.size();
}
}Java solution
matched/originalpublic class StringIterator {
StringBuilder res = new StringBuilder();
int ptr = 0;
public StringIterator(String s) {
int i = 0;
while (i < s.length()) {
char ch = s.charAt(i++);
int num = 0;
while (i < s.length() && Character.isDigit(s.charAt(i))) {
num = num * 10 + s.charAt(i) - '0';
i++;
}
for (int j = 0; j < num; j++)
res.append(ch);
}
}
public char next() {
return !hasNext() ? ' ' : res.charAt(ptr++);
}
public boolean hasNext() {
return ptr != res.length();
}
}JavaScript solution
matched/originalclass StringIterator {
constructor(s) {
this.res = [];
this.ptr = 0;
let i = 0;
while (i < s.length) {
let ch = s[i++];
let num = 0;
while (i < s.length && !isNaN(s[i])) {
num = num * 10 + parseInt(s[i]);
i++;
}
this.res.push(...Array(num).fill(ch));
}
}
next() {
return this.hasNext() ? this.res[this.ptr++] : ' ';
}
hasNext() {
return this.ptr < this.res.length;
}
}Python solution
matched/originalclass StringIterator:
def __init__(self, s: str):
self.res = []
self.ptr = 0
i = 0
while i < len(s):
ch = s[i]
i += 1
num = 0
while i < len(s) and s[i].isdigit():
num = num * 10 + int(s[i])
i += 1
self.res.extend([ch] * num)
def next(self) -> str:
if not self.hasNext():
return ' '
char = self.res[self.ptr]
self.ptr += 1
return char
def hasNext(self) -> bool:
return self.ptr < len(self.res)Go solution
matched/originalpackage main
type StringIterator struct {
res []rune
ptr int
}
func Constructor(s string) StringIterator {
res := []rune{}
i := 0
for i < len(s) {
ch := rune(s[i])
i++
num := 0
for i < len(s) && s[i] >= '0' && s[i] <= '9' {
num = num*10 + int(s[i]-'0')
i++
}
for j := 0; j < num; j++ {
res = append(res, ch)
}
}
return StringIterator{res: res, ptr: 0}
}
func (this *StringIterator) Next() rune {
if !this.HasNext() {
return ' '
}
ch := this.res[this.ptr]
this.ptr++
return ch
}
func (this *StringIterator) HasNext() bool {
return this.ptr < len(this.res)
}Explanation
Algorithm
Предварительная обработка
Мы заранее создаем несжатую строку. Для этого проходим по данному сжатому строковому представлению и добавляем несжатые буквы для каждой сжатой буквы в результирующий строковый строитель res. Чтобы найти количество несжатых букв, мы проходим по данному сжатому строковому представлению. Когда находим букву, определяем следующее за ней число, используя десятичную арифметику. Таким образом, получаем два элемента (букву и количество), необходимые для формирования текущего фрагмента несжатой строки.
Операция next()
Начинаем с проверки, есть ли еще несжатые буквы в строке. Если нет, hasNext() возвращает False, а next() возвращает пробел (' '). В противном случае возвращаем букву, на которую указывает ptr, указывающий на следующую букву для возврата. Перед возвратом буквы также обновляем ptr, чтобы указывать на следующую букву в res.
Операция hasNext()
Если указатель ptr выходит за пределы массива res, это указывает на то, что больше несжатых букв нет. В этом случае возвращаем False. В противном случае возвращаем True.
😎