题目
题解
题目本身比较好理解,明显是用栈进行处理,但是自我改用Java语言进行刷题以来,发现很多Java基本的结构和API不太熟悉。下面的题解来自官方网站,写的非常细节,总结一下里面出现的细节,权当复习Java基础内容。
class Solution {
public String decodeString(String s) {
StringBuilder temp = new StringBuilder();
int num = 0; // 重复次数
LinkedList<Integer> nums = new LinkedList<>(); // 记录重复的数字
LinkedList<String> res = new LinkedList<>(); // 记录当前左括号前的内容
for(Character c : s.toCharArray()){
if(c == '['){ //记录[前面的值
nums.addLast(num);
res.addLast(temp.toString());
num = 0;
temp = new StringBuilder();
}
else if(c==']'){
StringBuilder temp2 = new StringBuilder(); // 处理当前[]中的字符串
int cur_num = nums.removeLast();
for(int i=0;i<cur_num;i++) temp2.append(temp);
temp = new StringBuilder(res.removeLast()+temp2);
}
else if(c>='0' && c<='9') // 数字处理
num = num * 10 +Integer.parseInt(c+"");
else temp.append(c);
}
return temp.toString();
}
}
先作两点说明:
1.这道题需要记录‘[’前面的数字,但是对于题目提供的字符串中全都是字符,所以要考虑字符和数字之间转换的麻烦事,而且定义一个辅助栈不好存储两种类型。所以作者定义两种栈,一个存‘[’之前解析的数字,一个存字符串。
2.前面说到另一个辅助栈存储字符串,这个可能有点意外,正常不应该是栈里存一个个字符吗?这里作者存的是‘[’之前的字符串,避免来回出栈入栈操作。
比如:给定字符串:3[ab2[bc]],依次遍历,遇到‘[’则将3入数字栈,将""(空串)入字符串栈,再遇到‘[’将2入数字栈,将"ab"入字符串栈,遇到‘]’进行处理再放回栈。
从这两点就已经能看出这份代码的基本细节了。
解析
1.StringBuilder的使用
对于字符串的相关处理,我们肯定要使用StringBuilder这种不创建额外对象的工具。但是这个工具使用也有点奇怪。这里有几处用法:
(1)StringBuilder.append()——添加内容,比较宽松,可接收大部分基本数据类型、String、char[]等等,甚至接收StringBuilder。
StringBuilder sb = new StringBuilder();
sb.append(8).append("乘以").append(6.6).append('=').append(true);
sb.append(new StringBuilder("!!!"));
System.out.println(sb); // 输出结果为:8乘以6.6=true!!!
(2)StringBuilder和String类型的转换
StringBuilder sb = new StringBuilder();
String s = sb.toString(); // StringBuilder转String
StringBuilder sb2 = new StringBuilder(s); // String转StringBuilder
(3)清空 StringBuilder
可能一想就是StringBuilder.clear(),哈哈,可惜没有这个API,可以选择重新new StringBuilder(),这里代码的使用就是这样。
StringBuilder temp = new StringBuilder();
temp.append("hello");
temp = new StringBuilder(); // 清空StringBuilder
(4)复制字符串n次
本来想到的是String+=这种,但是已经在用StringBuilder处理了,转成String再转回来更麻烦。这里是重新new StringBuilder(),然后循环添加之前的StringBuilder。
StringBuilder temp2 = new StringBuilder(); // 处理当前[]中的字符串
int cur_num = nums.removeLast();
for(int i=0;i<cur_num;i++) temp2.append(temp); // 复制字符串n次
2.栈的使用
Java中是有栈的对象的,即Stack对象,但是一般不用,而是使用Collection集合对象下的一些对象,其实这些也满足栈的功能,哪怕定义一个String进行操作也有栈的先入后出特性。这里使用的是LinkedList集合定义两个辅助栈。
(1)包装类
List集合包括ArrayList和LinkedList两种,如果要定义操作基本数据类型的List,就要使用包装类。如int对应Integer类,char对应Character类。
LinkedList<Integer> nums = new LinkedList<>(); // 记录重复的数字
(2)LinkedList相关API
LinkedList.addLast()——元素添加到尾部
nums.addLast(num);
LinkedList.removeLast()——删除并返回最后一个元素,注意区别remove()
int cur_num = nums.removeLast();
3.遍历字符串
遍历一个String有几种常用办法:
String str="HelloWorld";
// 法一
for(int i=0;i < str.length();i++) {
System.out.println(str.charAt(i));
}
//法二
for(int i=0;i < str.length();i++) {
System.out.println(str.substring(i,i+1));
}
//法三
char[] c = str.toCharArray();
for(int i=0;i < c.length;i++) {
System.out.println(c[i]);
}
这里为了更好获得每一个字符,作者的方式很巧妙,先将s变为字符数组,再进行增强式for循环:
for(Character c : s.toCharArray()){}
4.对于数字的处理
要注意一点,就是题目中并没有说数字一定是个位数,也就是可能有"32[as]"这样的情况。‘3’和‘2’都是字符,那怎么拿到数字32呢?
作者使用Integer类的parseInt方法处理,但是这个方法参数是字符串?字符变为字符串使用字符+""的方式,即parseInt(字符+"")就得到字符对应的数字了。
又可能为多位数字,使用num=num*10的方式计算,数字处理完毕之后一定为‘[’,直接进行入栈,是不是很巧妙?
else if(c>='0' && c<='9') // 数字处理
num = num * 10 +Integer.parseInt(c+"");
总结
没想到一个简单的题目蕴含这么多东西,总结下来学会很多。这一份题解代码还有很多细节,只能说多刷多总结,Java基础才能牢固。