迭代压缩字符串
对于一个压缩字符串,设计一个数据结构,它支持如下两种操作: next 和 hasNext。
给定的压缩字符串格式为:每个字母后面紧跟一个正整数,这个整数表示该字母在解压后的字符串里连续出现的次数。
next() - 如果压缩字符串仍然有字母未被解压,则返回下一个字母,否则返回一个空格。
hasNext() - 判断是否还有字母仍然没被解压。
注意:
请记得将你的类在 StringIterator 中 初始化 ,因为静态变量或类变量在多组测试数据中不会被自动清空。更多细节请访问 这里 。
示例:
StringIterator iterator = new StringIterator(“L1e2t1C1o1d1e1”);
iterator.next(); // 返回 ‘L’
iterator.next(); // 返回 ‘e’
iterator.next(); // 返回 ‘e’
iterator.next(); // 返回 ‘t’
iterator.next(); // 返回 ‘C’
iterator.next(); // 返回 ‘o’
iterator.next(); // 返回 ‘d’
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 ‘e’
iterator.hasNext(); // 返回 false
iterator.next(); // 返回 ’ ’
当字符串重复次数很大时下面解法超时,如当字符串为a1212323234b2354235342
时
package com.company;
public class StringIterator {
private String str;
private int index = 0;
private char []deChars = null;
public StringIterator(String compressedString) {
str = compressedString;
deChars = decompressString().toCharArray();
}
public char next() {
if(hasNext()){
return deChars[index++];
}
return ' ';
}
public boolean hasNext() {
return index < deChars.length;
}
public String decompressString(){
/**
*快慢指针法解压字符串
* i指向字母,j指向下一个字母,i,j之间的数字为重复个数cnt
* 将i位置的字母重复cnt次,组成新的解压的字符串
* 时间O(n^2),空间O(n)
*/
StringBuffer sb = new StringBuffer();
int i = 0, j = i+1;
while(j < str.length()){
if(j+1 == str.length() || (str.charAt(j) >= 'a' && str.charAt(j) <= 'z')
|| (str.charAt(j) >= 'A' && str.charAt(j) <= 'Z')){
//当j走到最后最后一个元素时,要将其值变为字符串长度,以取子串时能取到最后
j = j+1 == str.length() ? str.length(): j;
String subNumStr = str.substring(i+1, j);
int cnt = Integer.parseInt(subNumStr);
while (cnt > 0){
sb.append(str.charAt(i));
cnt--;
}
i = j;
}
j++;
}
System.out.println(sb.toString());
return sb.toString();
}
public static void main(String []args){
/**
* ["StringIterator","next","next","next","next","next","next","hasNext","next","hasNext"]
* [["L2e2t2C2o2d2e23"],[],[],[],[],[],[],[],[],[]]
*/
StringIterator obj = new StringIterator("a1212323234b2354235342");
char param_1 = obj.next();
boolean param_2 = obj.hasNext();
System.out.println(param_1 + " " + String.valueOf(param_2));
char param_11 = obj.next();
boolean param_21 = obj.hasNext();
System.out.println(param_11 + " " + String.valueOf(param_21));
char param_12 = obj.next();
boolean param_22 = obj.hasNext();
System.out.println(param_12 + " " + String.valueOf(param_22));
}
}
下面的方法不需要先构建字符串,是需要的时候解压字符串
public class StringIterator {
/**
* 1.定义函数decompose,每次都能找到下一个需要打印的字符curChar和其数量curCnt,记录之,同时
* 如果找到就返回真,找不到返回假
* 2.判断是否有下一个元素的方法:如果curCnt>0,则代表当前的字符还没有打印完,当然有下一个字符,返回真
* 如果curCnt<=0,则说明当前字符已经打印完成,那就要看能不能找到下一个需要打印的字符了,调用decompose
* 就会知道有没有下一个需要打印的字符
*3.时间主要在decompose上,为O(n),空间O(1)
*/
private String str;
private int i = 0;
private int j = 1;
private char curChar;
private int curCnt = 0;
public StringIterator(String compressedString) {
str = compressedString;
}
public char next() {
if(hasNext()){
curCnt--;
return curChar;
}
return ' ';
}
public boolean hasNext() {
if (curCnt > 0){
return true;
}else{
return decompose();
}
}
public boolean decompose(){
if(j >= str.length()){
//表示是否还能够继续处理字符串
return false;
}
//j一直走到不为数字的位置
while(j < str.length() && str.charAt(j) >= '0' && str.charAt(j) <= '9'){
j++;
}
//j可能走到末尾,截取子串时需要下面处理
j = j+1 >= str.length() ? str.length(): j;
String subNumStr = str.substring(i+1, j);
int cnt = Integer.parseInt(subNumStr);
//记录当前的字符和数量
curChar = str.charAt(i);
curCnt = cnt;
//下一次调用函数的时候i和j的位置
i = j;
j++;
//表示是否处理了字符串,有结果出来
return true;
}
public static void main(String []args){
StringIterator obj = new StringIterator("L2342e2");
boolean param_2= true;
while (param_2){
char param_1 = obj.next();
param_2 = obj.hasNext();
System.out.println(param_1 + " " + String.valueOf(param_2));
}
}
}
上面的代码decompose部分太过于繁琐,简化处理后为
package com.company;
public class StringIterator {
/**
* 1.定义函数decompose,每次都能找到下一个需要打印的字符curChar和其数量curCnt,记录之,同时
* 如果找到就返回真,找不到返回假
* 2.判断是否有下一个元素的方法:如果curCnt>0,则代表当前的字符还没有打印完,当然有下一个字符,返回真
* 如果curCnt<=0,则说明当前字符已经打印完成,那就要看能不能找到下一个需要打印的字符了,调用decompose
* 就会知道有没有下一个需要打印的字符
*3.时间为O(1),空间O(1)
*/
private String str;
private int i = 0;
private char curChar;
private int curCnt = 0;
public StringIterator(String compressedString) {
str = compressedString;
}
public char next() {
if(hasNext()){
curCnt--;
return curChar;
}
return ' ';
}
public boolean hasNext() {
return curCnt > 0 || decompose();
}
public boolean decompose(){
if(i >= str.length()){
return false;
}
curChar = str.charAt(i++);
curCnt = 0;
while (i < str.length() && Character.isDigit(str.charAt(i))){
curCnt += curCnt * 10 + str.charAt(i++) - '0';
}
return true;
}
public static void main(String []args){
StringIterator obj = new StringIterator("L2342e2");
boolean param_2= true;
while (param_2){
char param_1 = obj.next();
param_2 = obj.hasNext();
System.out.println(param_1 + " " + String.valueOf(param_2));
}
}
}