时间复杂度:O(n),空间复杂度:O(n)
解题思路
千万别看只用一个栈的题解,理解起来很困难。其实这道题用两个栈的解法是最易理解的,而且空间复杂度都是O(n)!
创建两个栈,一个专门用来存放数字,一个专门用来存放字母字符串。每当遇到右括号时,就取出字母栈和数字栈的栈顶元素str和k并令二者出栈,表示要将str重复k次,完成之后让字母栈栈顶元素加上str,等待下一次重复。也就是说,要保证字母栈的栈顶始终是等待重复的字母串,字母栈的栈底元素就是最后的结果。
实现过程中需要注意的是,要先将一个空字符串追加到字母栈中,该字符串最后就是结果。
Go语法方面需要注意的是,string只能拼接string,所以遍历时下标表示的byte要用切片表示转换成string,这样就可以string拼接了。还有就是atoi函数是将string转换为int,处理字符串时经常会用到。
AC代码
func decodeString(s string) string {
strStack,numStack:=[]string{},[]int{}
strStack=append(strStack,"")//字母串栈栈底就是结果,一开始置为空
num:=""//待放入数字栈的重复次数
for i:=0;i<len(s);i++{
if s[i]>='a'&&s[i]<='z'{
strStack[len(strStack)-1]+=s[i:i+1]//栈顶始终是等待重复的字母串
}else if s[i]>='0'&&s[i]<='9'{
num+=s[i:i+1]
}else if s[i]=='['{
k:=strconv.Atoi(num)//将string类型的重复次数转换为int类型
numStack=append(numStack,k)//遇到左括号了,k计算结束可以入栈了
num=""//重置,等待下一次计算重复次数
strStack=append(strStack,"")//保证栈顶是等待重复的字母串
}else{
k:=numStack[len(numStack)-1]//重复次数
numStack=numStack[:len(numStack)-1]
str:=strStack[len(strStack)-1]//重复的字符串
strStack=strStack[:len(strStack)-1]//注意此时等待重复的字符串已经出栈,栈顶变为重复次数前面的字母串
for i:=0;i<k;i++{
strStack[len(strStack)-1]+=str
}
}
}
return strStack[0]//栈顶就是结果
}
感悟
非常讨厌字符串的题,一个原因就是总是会涉及到string转int、int转string这种类型转换,再加上go的字符串数字互转限制还比较多,而且还有一个rune类型,总体而言写起来有点费劲,不如c艹……
不过这次学习到了strconv包的Atoi函数专门用来将字符串数字转为int类型数字,以后可能会经常用到的。