Open azl397985856 opened 3 years ago
/**
* @param {string} s
* @return {string}
*/
var decodeString = function (s) {
let stack = [], num = '', str = '';
for (let i of s) {
if (/^[0-9]+.?[0-9]*$/.test(i)) { //如果是数字
num += i
} else if (i == '[') { //遇到下一个的开头 入栈
stack.push({
num: num,
str: str
})
num = '';
str = '';
} else if (i == ']') { //出栈
let top = stack.pop()
str = top.str + str.repeat(top.num)
} else { // 如果是字母
str += i
}
}
return str
};
public class Solution {
public String decodeString(String s) {
String res = "";
Stack<Integer> countStack = new Stack<>();
Stack<String> resStack = new Stack<>();
int idx = 0;
while (idx < s.length()) {
Character c = s.charAt(idx);
if (Character.isDigit(c)) {
int count = 0;
while (Character.isDigit(c)) {
count = 10 * count + (c - '0');
idx++;
}
countStack.push(count);
}
else if (c == '[') {
resStack.push(res);
res = "";
idx++;
}
else if (c == ']') {
StringBuilder temp = new StringBuilder (resStack.pop());
int repeatTimes = countStack.pop();
for (int i = 0; i < repeatTimes; i++) {
temp.append(res);
}
res = temp.toString();
idx++;
}
else {
res += s.charAt(idx++);
}
}
return res;
}
}
类似题目
从后往前遍历获取最完整的substring
[]
包裹的substring, 然后进栈class Solution:
def decodeString(self, s: str) -> str:
stack=[]
i = len(s)-1
while i>=0:
# If value is not a digit, append all the character
if not s[i].isdigit():
stack.append(s[i])
i-=1
else:
# If value is a digit, get the value
num=''
while i>=0 and s[i].isdigit():
num=s[i]+num
i-=1
# Find the substring, by popping all bracket characters
sub=''
while stack[-1]!=']':
tmp=stack.pop()
if tmp!='[':
sub+=tmp
stack.pop()
sub=int(num)*sub # Perfrom recurring substring
stack.append(sub)
stack.reverse()
return ''.join(stack)
/**
* @param {string} s
* @return {string}
*/
var decodeString = function (s) {
let stack = [],
str = [],
res = '',
num = 0
for (const char of s) {
if (char == '[') {
stack.push(num)
str.push(res)
res = ''
num = 0
} else if (char == ']') {
res = str.pop() + res.repeat(stack.pop())
} else if (!isNaN(char)) {
num = num * 10 + Number(char)
} else {
res += char
}
}
return res
}
栈的思路去实现
function decodeString(S) {
let stack = [];
let numstr = '';
for (let s of S) {
if (Number.isInteger(+s)) {
numstr += s;
continue;
}
if (numstr) {
stack.push(+numstr);
numstr = '';
}
if (s != ']') {
stack.push(s);
continue;
}
let str = '';
while (stack.length && stack.slice(-1) != '[') {
let top = stack.pop();
top += str;
str = top;
}
stack.pop();
let count = +stack.pop();
let pushStr = str.repeat(count);
stack.push(pushStr);
}
return stack.join('');
}
维护两个栈去存储字符和数字。 比较困难的是在碰到']'的时候,去字符串顶获取当前已经保存的字符,重复k遍后加到栈顶。 然后把栈顶的元素赋给cur_str,弹出字符串的栈顶元素。 最终的结果就是保留在cur_str中。
class Solution {
public:
string decodeString(string s) {
int s_len = s.size();
stack<int> numstack;
stack<string> strstack;
int num = 0;
string cur_str="";
string res = "";
for(int i = 0; i < s_len; i++) {
if(s[i]>='0' && s[i]<='9') {
num = 10*num + s[i]-'0';
}
else if((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<'Z')) {
cur_str += s[i];
// cout<< cur_str;
}
else if(s[i]=='['){
strstack.push(cur_str);
numstack.push(num);
num = 0;
cur_str="";
}
else if(s[i]==']'){
int k = numstack.top();
numstack.pop();
for(int j = 0; j <k; j++){
strstack.top() += cur_str;
}
cur_str = strstack.top();
strstack.pop();
}
}
return cur_str;
}
};
时间复杂度:O(N) 空间复杂度:O(N)
思路: 用两个堆栈,当遇到数字,数字*10累加。遇到'[',将数字压入数字栈,字符串压入字符串栈。遇到']'将重复次数提出来,将]前的字符串重复拼接,除此之外就是继续拼接现有字符串。
关键:strings.Repeat 调用 从string 获取字符串 , string(s[i]) 特别是string 获取单个字符,就string(s[i]) 若有数字就 strconv.Atoi
代码:
func decodeString(s string) string {
stack1 := []int{}
stack2 := []string{}
byte := ""
count := 0
for i:=0; i < len(s); i++{
if s[i] >= '0' && s[i] <= '9'{
n, _ := strconv.Atoi(string(s[i]))
count = count *10 + n
}else if s[i] == '['{
stack1 = append(stack1, count)
count = 0
stack2 = append(stack2, byte)
byte = ""
}else if s[i] == ']'{
num := stack1[len(stack1)-1]
stack1 = stack1[:len(stack1)-1]
out := stack2[len(stack2)-1]
stack2 = stack2[:len(stack2)-1]
byte = string(out) + strings.Repeat(byte, num)
}else{
byte += string(s[i])
}
}
return byte
}
时间复杂度:O(n) 空间复杂度:O(n)
递归。
"[": 开启新的一轮递归。 并且生成字符串。
"]": 返回字符串内容, 并结束当前字符串。
class Solution:
def decodeString(self, s: str) -> str:
def dfs(position: int):
res = ""
multi_round = 0
while position < len(s):
if '0' <= s[position] <= '9':
multi_round = multi_round*10 + int(s[position])
elif s[position] == '[':
position, tmp = dfs(position + 1)
res += multi_round * tmp
multi_round = 0
elif s[position] == ']':
return position, res
else:
res += s[position]
position += 1
return res
return dfs(0)
思路
利用string ,栈完成,栈用于括号匹配和保存运算完成后的结果
代码 C++
class Solution { public: string decodeString(string s) { stack<string> q; int n=s.size(); string num="",str="",ans=""; for(int i=0;i<n;i++) { if(s[i]>='0'&&s[i]<='9') num+=s[i]; else { if(num!="") { q.push(num); num=""; } if(s[i]=='['||(s[i]>='a'&&s[i]<='z')) { str+=s[i]; q.push(str); str=""; } else if(s[i]==']') { string t=""; string cmp="["; while(q.top()!=cmp) { t=q.top()+t; q.pop(); } q.pop(); int m=stoi(q.top()); string k=t; for(int j=0;j<m-1;j++) t+=k; q.pop(); q.push(t); } } } string t2=""; while(!q.empty()) { t2=q.top()+t2; q.pop(); } ans+=t2; return ans; } };
复杂度分析
- 时间复杂度:O(N)
- 空间复杂度:O(N)
思路
建立一个空字符串来储存遍历过的字母,遇到左括号,就将之前的字符串和数字存到一个临时的栈中,遇到右括号时取出,之后按照规则进行连接
代码
class Solution:
def decodeString(self, s: str) -> str:
stack = []
str_new = ''
num = 0
for i in s:
if i.isdigit():
num = num * 10 + int(i) # 处理连续数字
elif i.isalpha():
str_new += i # 将不在括号内的字母存为一个新的字符串
elif i == '[':
stack.append((str_new, num)) # 遇到左括号,将之前的字符串和数字存起来
str_new, num = '', 0 # 重新初始化
else:
str_old, num_cur = stack.pop() # 遇到右括号,取出之前的字符串和数字
str_new = str_old + num_cur * str_new # 重复新的字符串,并与之前的字符串相连
return str_new
复杂度分析
// 9-13 cpp 栈
class Solution {
public:
string decodeString(string s) {
stack<int> nums;
stack<string> let;
int num = 0;
string res = "";
for (auto i : s) {
if (i >= '0' && i <= '9') {
// 注意多位数
num = num * 10 + i - '0';
}
else if (i == '[') {
nums.push(num);
num = 0;
let.push(res);
res = "";
}
else if (i == ']') {
int k = nums.top();
nums.pop();
string temp = let.top();
for (int i = 0; i < k; i++) {
temp += res;
}
res = temp;
let.pop();
}
else {
res += i;
}
}
return res;
}
};
时间复杂度: O(n)
空间复杂度: O(n)
根据栈的特点 先进后出 还有括号的判断 在讲义中有提到
class Solution:
def __init__(self, S):
self.S = S
def RecodeString(self):
stack = []
result = ""
for c in self.S:
if c == ']':
reStr = ''
reCount = ''
while stack and stack[-1] != '[':
reStr = stack.pop() + reStr
stack.pop()
while stack and stack[-1].isnumeric():
reCount = stack.pop() + reCount
stack.append(reStr * int(reCount))
else:
stack.append(c)
return result.join(stack)
O(N) N为输入的数组长度
定义一个数值记录[前的倍数,再定义一个记录[]中的字符串,当遇到]时,执行一个循环将中括号中的字符串遍历输出其的倍数次,如果字符串大于0或者小于9且不在括号里边的时候,就证明前面的数字不是个位数,需要相乘相加,得到多位数正确的值,
class Solution {
public String decodeString(String s) {
StringBuilder res= new StringBuilder();
int no=0;
LinkedList<Integer> stack_no=new LinkedList<>();
LinkedList<String> stack_res=new LinkedList<>();
for(Character c:s.toCharArray()){
if(c=='['){
//记录倍数
stack_no.addLast(no);
//开始在尾部添加新遍历到的元素
stack_res.addLast(res.toString());
no=0;
res=new StringBuilder();
}else if(c==']'){
StringBuilder tmp=new StringBuilder();
int tmo_no=stack_no.removeLast();
for(int i=0;i<tmo_no;i++){
tmp.append(res);
}
res=new StringBuilder(stack_res.removeLast()+tmp);
}else if(c>='0'&&c<='9'){
no=no*10+Integer.parseInt(c+"");
}else
res.append(c);
}
return res.toString();
}
}
时间复杂度O(N)
class Solution {
public String decodeString(String s) {
//定义结果
StringBuffer buffer = new StringBuffer();
//用来 定义字符栈
LinkedList<String> listString = new LinkedList<>();
// 用来定义数字栈
LinkedList<Integer> listInt = new LinkedList<>();
for(int i = 0;i<s.length();){
if(s.charAt(i)!=']'){
char a = s.charAt(i);
if(a>'9' || a<'0'){
//进入字符栈中
listString.add(a+"");
i++;
}else{
//就是数字,进入数字栈中
int j = i+1;
int tem = a-'0';
while(s.charAt(j)<='9' && s.charAt(j)>='0' && j<s.length()){
tem = tem *10 + (s.charAt(j)-'0');
j++;
}
i = j;
listInt.add(tem);
}
}else{
//用来取出字符栈中的元素
String temString = new String();
//用来拿出栈顶的数字
int temInt = listInt.getLast();
listInt.removeLast();
// 循环拿出 字符
while(!listString.isEmpty() && !listString.getLast().equals("[")){
temString = listString.getLast()+temString;
listString.removeLast();
}
listString.removeLast();
StringBuffer sb = new StringBuffer();
for(int k = 1;k<=temInt;k++){
sb.append(temString);
}
//如果说listInt不是空的,就将结果压在listString栈中
if(!listInt.isEmpty()){
listString.add(sb.toString());
}else{
//反之,加到结果中
String ss = "";
while(!listString.isEmpty()){
ss = listString.getLast()+ss;
listString.removeLast();
}
buffer.append(ss);
buffer.append(sb);
}
i++;
}
}
if(!listString.isEmpty()){
for(int i =0;i<listString.size();i++){
buffer.append(listString.get(i));
}
}
return buffer.toString();
}
}
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
var strStack = []
var numStack = []
var num = ''
var res = ''
for(let c of s){
if (!isNaN(c)) { //是数字
num += c
//1位数以上的数字,不能立即入栈
} else if (c === '[') { //[ 字符串入栈 , 数字也入栈
strStack.push(res)
res = ''
numStack.push(num)
num = ''
} else if (c === ']') { // 双出栈
var times = numStack.pop()
var str = strStack.pop()
res = str + res.repeat(times)
} else {
res += c
}
}
return res
};
N是字符串s解码后新字符串的长度,S是字符串s的长度
还未解答出来,明天继续
class Solution {
public:
string decodeString(string s) {
vector<int> count;
vector<int> flag; //括号的下标
vector<vector<string>> str;//处理多重括号
int size = s.size();
for(int i=0; i<size; ++i)
{
if(isdigit(s[i]))
{
count.push_back(s[i]);
flag.push_back(++i); //[的下标
vector<string> f{"["};
str.push_back(f);
}
else if(s[i] ==']')
{
string in;
for(int j=flag.back(); j<i; ++j)//获取[]中的字符
{
in.push_back();
}
string temp;
for(int j=0; j<count.back(); ++j)//翻倍
{
temp.append(in);
}
}
else
{
}
}
return res;
}
};
class Solution {
public:
string decodeString(string s) {
int s_len = s.size();
stack<int> numstack;
stack<string> strstack;
int num = 0;
string cur_str="";
string res = "";
for(int i = 0; i < s_len; i++) {
if(s[i]>='0' && s[i]<='9') {
num = 10*num + s[i]-'0';
}
else if((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<'Z')) {
cur_str += s[i];
// cout<< cur_str;
}
else if(s[i]=='['){
strstack.push(cur_str);
numstack.push(num);
num = 0;
cur_str="";
}
else if(s[i]==']'){
int k = numstack.top();
numstack.pop();
for(int j = 0; j <k; j++){
strstack.top() += cur_str;
}
cur_str = strstack.top();
strstack.pop();
}
}
return cur_str;
}
};
两个列表,一个记录数字(即倍数),一个记录字母
``
public class Solution {
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
int multi = 0;
LinkedList<Integer> stack_multi = new LinkedList<>();
LinkedList<String> stack_res = new LinkedList<>();
for(Character c : s.toCharArray()) {
if(c == '[') {
stack_multi.addLast(multi);
stack_res.addLast(res.toString());
multi = 0;
res = new StringBuilder();
}
else if(c == ']') {
StringBuilder tmp = new StringBuilder();
int cur_multi = stack_multi.removeLast();
for(int i = 0; i < cur_multi; i++) {
tmp.append(res);
}
res = new StringBuilder(stack_res.removeLast() + tmp);
}
else if(c >= '0' && c <= '9') {
//如果是数字
multi = multi * 10 + Integer.parseInt(c + "");
}
else {
//如果是字母
res.append(c);
}
}
return res.toString();
}
}
时间复杂度:O(N),一次遍历 s; 空间复杂度:O(N),辅助栈在极端情况下需要线性空间
记录此 [ 前的临时结果 res 至栈,用于发现对应 ] 后的拼接操作; 记录此 [ 前的倍数 multi 至栈,用于发现对应 ] 后,获取 multi × [...] 字符串。 进入到新 [ 后,res 和 multi 重新记录。
last_res是上个 [ 到当前 [ 的字符串,例如 "3[a2[c]]" 中的 a; cur_multi是当前 [ 到 ] 内字符串的重复倍数,例如 "3[a2[c]]的2.
class Solution {
public:
string decodeString(string s) {
int n=s.size();
vector<int> numS;
vector<string> charS;
int a=0;
string ret;
for(int i=0;i<n;i++){
if(isdigit(s[i])){
a=a*10+s[i]-'0';
}else if( s[i]=='['){
numS.push_back(a);
string tmp;
charS.push_back(tmp);
a=0;
}else if( s[i]==']'){
int num=numS.back();
string s1=charS.back();
charS.pop_back();
if(charS.size())
{
for(int i=0; i< num; i++){
charS.back() +=s1;
}
}else {
for(int i=0; i< num; i++){
ret +=s1;
}
}
numS.pop_back();
}else{
if(charS.size()){
charS[charS.size()-1].push_back(s[i]);
}else{
ret.push_back(s[i]);
}
}
}
return ret;
}
};
遍历一遍s需要的时间为O(s.size());
1.思路 本题难点在于括号内嵌套括号,需要从内向外生成与拼接字符串,这与栈的先入后出特性对应。 ①构建辅助栈 stack, 遍历字符串 s 中每个字符 c; ②当 c 为数字时,将数字字符转化为数字 multi,用于后续倍数计算; ③当 c 为字母时,在 res 尾部添加 c; ④当 c 为 [ 时,将当前 multi 和 res 入栈,并分别置空置 00: 记录此 [ 前的临时结果 res 至栈,用于发现对应 ] 后的拼接操作; 记录此 [ 前的倍数 multi 至栈,用于发现对应 ] 后,获取 multi × [...] 字符串。 进入到新 [ 后,res 和 multi 重新记录。
⑤当 c 为 ] 时,stack 出栈,拼接字符串 res = last_res + cur_multi * res,其中: last_res是上个 [ 到当前 [ 的字符串,例如 "3[a2[c]]" 中的 a; cur_multi是当前 [ 到 ] 内字符串的重复倍数,例如 "3[a2[c]]的2.
2.代码
class Solution {
public:
string decodeString(string s) {
int n=s.size();
vector
}else {
for(int i=0; i< num; i++){
ret +=s1;
}
}
numS.pop_back();
}else{
if(charS.size()){
charS[charS.size()-1].push_back(s[i]);
}else{
ret.push_back(s[i]);
}
}
}
return ret;
}
};
3.复杂度
遍历一遍s需要的时间为O(s.size());
使用栈结构,
滑动窗口模型判断一个完整的数字
字符串乘法
倒叙叠加字符串
function checkRate(input) {
var re = /^[0-9]+.?[0-9]*/;
//判断字符串是否为数字//判断正整数/[1−9]+[0−9]∗]∗/;//判断字符串是否为数字//判断正整数/[1−9]+[0−9]∗]∗/
return re.test(input);
}
var decodeString = function (s) {
const stack = [];
let numStr = '';
for (let i = 0; i < s.length; i++) {
if (checkRate(s[i])) {
numStr += s[i];
continue;
} else {
if (numStr) stack.push(numStr);
numStr = '';
if (s[i] !== ']') {
stack.push(s[i]);
} else {
let tempStr = '';
while (stack.length) {
const curStr = stack.pop();
if (curStr !== '[') {
tempStr = curStr + tempStr;
} else {
break;
}
}
let curNum = stack.pop();
stack.push(tempStr.repeat(curNum));
}
}
}
return stack.join('');
}
定义一栈来存储计算,当前字符不为 ‘】‘就直接存入到栈中,当前的字符为’]‘的时候,则就是要出栈的时候,直到栈顶为’[’,然后将‘[’出栈,再判断栈顶是否为数字(注意存在的数字可能是二位数一样),再通过所得的字符转,算出字符串并进行入栈,再取下一位字符进行判断,重复以上的操作。
class Solution { public String decodeString(String s) { int n=s.length(); int i=0; Stack<String> stack=new Stack<String>(); while(i<n){ char temp=s.charAt(i); if(temp!=']'){ stack.push(temp+""); }else{ String temp_string = ""; String temp_string2= ""; int count=0; while(fun(stack.peek())){ //取到栈顶为【为止 temp_string=stack.pop()+temp_string; } stack.pop();//[出栈 double num=0.0; while(!stack.isEmpty()){ //继续从栈中取 直到栈顶不为数字为止 if(Character.isDigit(stack.peek().charAt(0))){ count=Integer.parseInt(stack.peek())*(int)Math.pow(10.0,num)+count; num++; }else{ break; } stack.pop(); } while (count>0){ temp_string2 += temp_string; count--; } stack.push(temp_string2); } i++; } String res=""; while (!stack.isEmpty()){ res=stack.pop()+res; } return res; } public boolean fun(String s){ if(s.length()>1)return true; if(s.equals("["))return false; return true; } }
时间复杂度:(有点分析不来。。。)
空间复杂度:O(N)
'[' 出栈
#-*- coding : utf-8 -*-
'''
字符串解码
输入:s = "3[a2[c]]"
输出:"accaccacc"
'''
def decodeString(s):
stack = []
for i in s:
if i == ']':
reStr = ''
reCount = ''
while stack and stack[-1] != '[':
reStr = stack.pop() + reStr
stack.pop()
while stack and stack[-1].isnumeric():
reCount = stack.pop() + reCount
stack.append(reStr*int(reCount))
else:
stack.append(i)
return "".join(stack)
if name == 'main': print(decodeString("3[a2[c]]"))
准备两个栈,一个存数字,一个存翻倍字符串
class Solution {
public:
string getDigits(string &s, size_t &ptr) {
string ret = "";
while (isdigit(s[ptr])) {
ret.push_back(s[ptr++]);
}
return ret;
}
string getString(vector <string> &v) {
string ret;
for (const auto &s: v) {
ret += s;
}
return ret;
}
string decodeString(string s) {
vector <string> stk;
size_t ptr = 0;
while (ptr < s.size()) {
char cur = s[ptr];
if (isdigit(cur)) {
// 获取一个数字并进栈
string digits = getDigits(s, ptr);
stk.push_back(digits);
} else if (isalpha(cur) || cur == '[') {
// 获取一个字母并进栈
stk.push_back(string(1, s[ptr++]));
} else {
++ptr;
vector <string> sub;
while (stk.back() != "[") {
sub.push_back(stk.back());
stk.pop_back();
}
reverse(sub.begin(), sub.end());
// 左括号出栈
stk.pop_back();
// 此时栈顶为当前 sub 对应的字符串应该出现的次数
int repTime = stoi(stk.back());
stk.pop_back();
string t, o = getString(sub);
// 构造字符串
while (repTime--) t += o;
// 将构造好的字符串入栈
stk.push_back(t);
}
}
return getString(stk);
}
};
时间:O(n)
空间:O(n)
解法可能过于简单粗暴,时间比较紧先记录下解题
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for i in s:
if i == ']':
strs = ''
repeat = ''
while stack[-1] != '[':
strs = stack.pop() + strs
stack.pop()
while stack and stack[-1].isdigit():
repeat = stack.pop() + repeat
stack.append(int(repeat) * strs)
continue
stack.append(i)
return ''.join(stack)
class Solution {
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
int times = 0;
LinkedList
for(Character c : s.toCharArray()){
if(c == '[') {
multi.addLast(times);
stack.addLast(res.toString());
times = 0;
res = new StringBuilder();
}
else if(c == ']'){
StringBuilder tmp = new StringBuilder();
int cur_multi = multi.removeLast();
for(int i =0 ;i<cur_multi; i++){tmp.append(res);};
res = new StringBuilder(stack.removeLast() + tmp);
}
else if(c >= '0' && c <= '9'){times = times * 10 + Integer.parseInt(c + "");}
else res.append(c);
}
return res.toString();
}
}
定义两个栈char_list,numList. char_list用来存放最后要输出的字符串的数组 num_list用来存放每个s中的数字在char_list中的位置 遍历s 遇到小写字母直接存入 遇到数字时继续读取字符查看数字有几位,拼接成1个数字比如["1","0","0"]转化为“100”存入char_list中,将该位置的值存入num_list中 遇到'['不做处理 遇到']'取出num_list中的栈顶元素(上一个数字的位置),将当前位置的数字取出转化为int(),取出那个位置后的所有char_list中的字符,相乘后存入char_list中 最后以字符串形式输出数组中的所有元素
class Solution:
def decodeString(self, s: str) -> str:
'字符串列表'
char_list = [0 for _ in range(10000)]
char_flag = -1
num_list = [0 for _ in range(len(s))]
num_flag = -1
i = 0
while i < len(s):
if 'a' <= s[i] <= 'z':
char_flag += 1
char_list[char_flag] = s[i]
elif '0' <= s[i] <= '9':
num_length = 1
while '0' <= s[i + 1] <= '9':
num_length += 1
i += 1
head = i - num_length + 1
tail = i + 1
a = s[head:tail]
num_char = ''.join(a)
char_flag += 1
char_list[char_flag] = num_char
num_flag += 1
num_list[num_flag] = char_flag
elif ']' == s[i]:
# 取出字符串要乘的倍数
mutiple_num = int(char_list[num_list[num_flag]])
# 取出被乘的字符串
head = num_list[num_flag] + 1
tail = char_flag + 1
str = "".join(char_list[head:tail])
# 乘好后的字符串
mutiple_str = mutiple_num * str
# 将指针倒退回上一个数字位置
char_flag = num_list[num_flag] - 1
for data in mutiple_str:
char_flag += 1
char_list[char_flag] = data
num_flag -= 1
i += 1
final_str = "".join(char_list[0:char_flag + 1])
return final_str
时间: O(n^2) 空间: O(n)
class Solution {
public String decodeString(String s) {
//Deque<String> letterStack = new LinkedList<String>();
//Deque<String> numStack = new LinkedList<Integer>();
Deque<String> stack = new LinkedList<String>();
for (int i = 0; i < s.length(); i++) {
if (']' != s.charAt(i)) {
stack.push(String.valueOf(s.charAt(i)));
} else {
StringBuffer letterSb = new StringBuffer();
while (Character.isLetter(stack.peek().charAt(0)) && stack.peek().charAt(0) != '[') {
letterSb.insert(0,stack.pop());
}
stack.pop();
StringBuffer numSb = new StringBuffer();
while ( !stack.isEmpty() && Character.isDigit(stack.peek().charAt(0))) {
numSb.insert(0,stack.pop());
}
int count = Integer.parseInt(numSb.toString());
StringBuffer sb = new StringBuffer();
while (count > 0) {
sb.append(letterSb.toString());
count--;
}
stack.push(sb.toString());
}
}
StringBuffer resbuff = new StringBuffer();
for(String str : stack) {
resbuff.insert(0,str);
}
return resbuff.toString();
}
}
使用双栈,碰到 [
数字和当前字符串入栈,碰到 ]
数字和字符串出栈。
var decodeString = function(s) {
const countStack = [], strStack = [] // 一个放倍数,一个放拼接的
let num = 0, result = ''
for (const ch of s) {
if (!isNaN(ch)) num = num * 10 + Number(ch)
else if (ch === '[') {
strStack.push(result)
result = ''
countStack.push(num)
num = 0
} else if (ch === ']') {
const count = countStack.pop()
result = strStack.pop() + result.repeat(count)
} else result += ch
}
return result
};
时间复杂度: O(n)
空间复杂度: O(n)
遍历s, 如果遇到数字和字符串,拼接起来,遇到[
则把拼接后的数字和字符串存起来,遇到]
则把存起来的数字和字符串取出来,用数字倍数拼接字符串
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
let repeatNum = []
let repeatStr = []
let str = ''
let num = ''
for (const c of s) {
if (!isNaN(c)) {
num += c
} else if (c ==='[') {
repeatStr.push(str)
repeatNum.push(Number(num))
str = ''
num = ''
} else if (c === ']') {
str = repeatStr.pop() + str.repeat(repeatNum.pop())
} else {
str += c
}
}
return str
};
时间复杂度O(n) 空间复杂度O(m+n)
思路:
一般遇到括号类的首先应该想到栈
代码:
class Solution {
int p;
public String decodeString(String s) {
LinkedList<String> stack = new LinkedList<>();
p = 0;
while(p < s.length()){
char ch = s.charAt(p);
if(Character.isDigit(ch)){
stack.addLast(getDigital(s));
}else if(ch == '[' || Character.isLetter(ch)){
stack.addLast(String.valueOf(ch));
p++;
}else{
p++;
LinkedList<String> subStr = new LinkedList<>();
while(!"[".equals(stack.peekLast())){
subStr.add(stack.removeLast());
}
Collections.reverse(subStr);
stack.removeLast();
int repCount = Integer.parseInt(stack.removeLast());
String repStr = getString(subStr);
StringBuffer sb = new StringBuffer();
while(repCount > 0){
sb.append(repStr);
repCount--;
}
stack.addLast(sb.toString());
}
}
return getString(stack);
}
public String getDigital(String s){
StringBuffer sb = new StringBuffer();
while(Character.isDigit(s.charAt(p))){
sb.append(String.valueOf(s.charAt(p)));
p++;
}
return sb.toString();
}
public String getString(List<String> list){
StringBuffer sb = new StringBuffer();
for(String s : list)
sb.append(s);
return sb.toString();
}
}
复杂度分析:
类似括号匹配,遍历字符串, 如果是数字,就计算当前数字; 如果是字符,入栈; 如果是左括号,先把当前计算好的数字入栈,再把左括号入栈; 如果是右括号,先把栈顶字符串依次出栈并拼接起来,直到碰到左括号。左括号出栈后,栈顶是重复次数,根据次数展开当前字符串后入栈。 遍历结束后把栈内所有已解码完成的字符串拼接起来。
/**
@return {string} */
var decodeString = function(s) {
let stack = [];
let num = 0;
for (let i=0; i<s.length; i++) {
if (s[i] >= '0' && s[i] <= '9') {
num = num * 10 + (s[i] - '0');
} else if (s[i] === '[') {
stack.push(num);
num = 0;
stack.push(s[i]);
} else if (s[i] === ']') {
let str = '';
while (stack[stack.length - 1] !== '[') {
str = stack.pop() + str;
}
stack.pop(); // '['
let temp = '';
let repeat = stack.pop();
while (repeat > 0) {
temp += str;
repeat--;
}
stack.push(temp);
} else {
// chars
stack.push(s[i]);
}
}
let ans = '';
while (stack.length !== 0) {
ans = stack.pop() + ans;
}
return ans;
};
TC: O(ans.length) SC: O(ans.length)
不是']'就全部入栈,碰到']'开始解码,解码就是一个个拆出来,碰到'['停止拆字符串,碰到数字就另外算要重复的数字是多少。这里有两个地方容易错,一个是数字未必是个位数,一个是出栈之后的str不要直接拼到结果上,继续入栈(不然这样的case无法通过"3[a2[c]]"),最后把栈当作结果join一下即可。
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for i, char in enumerate(s):
if char != ']':
stack.append(char)
elif char == ']':
repeat_s = ''
while stack and stack[-1] != '[':
repeat_s = stack.pop() + repeat_s
stack.pop() # pop 掉'['
cnt = ''
while stack and stack[-1].isdigit(): # 可能有多个数字
cnt = stack.pop() + cnt
repeat_s = repeat_s * int(cnt)
stack.append(repeat_s) # 这里是一个要点,重复的字符串直接压回栈里
return ''.join(stack)
辅助栈
class Solution {
public:
string decodeString(string s) {
int multi = 0;
stack<int>stk_multi;
stack<string>stk_res;
string res = "";
for(int i =0;i<s.size();i++)
{
if(s[i]=='[')
{
stk_multi.push(multi);
stk_res.push(res);
multi = 0;
res = "";
}
else if(s[i]==']')
{
string temp = "";
int curmulti = stk_multi.top();
stk_multi.pop();
for(int i = 0;i<curmulti;i++)
{
temp+=res;
}
res = stk_res.top()+temp;
stk_res.pop();
}
else if(isdigit(s[i])) multi = multi*10 + s[i]-'0';
else res+=s[i];
}
return res;
}
};
/**
* @param {string} s
* @return {string}
*/
var decodeString = function (s) {
const stack = [];
for (let char of s) {
if (char === ']') {
let repeatRes = '', repeats = '';
let str = stack.pop();
while (str !== '[') {
repeatRes = str + repeatRes;
str = stack.pop()
}
let num = stack.pop()
while (!isNaN(num)) {
repeats = num + repeats;
num = stack.pop()
}
stack.push(num);//多弹出的字符串
repeatRes = repeatRes.repeat(parseInt(repeats));
stack.push(repeatRes)
} else {
stack.push(char)
}
}
return stack.join('')
};
class 字符串解码_394{
public String decodeString(String s) {
// 遇到[开始把前面一个入栈 以及后面的
Deque
String res = ""; // 存储本次[] 中的字符串 int num = 0; // 存储本次[ 前面的倍数 for(char c : s.toCharArray()) { if(c >= '0' && c <= '9') { // 是数字 num = num * 10 + (c - '0'); // 23[ab] 这种 数字是23倍 } else if( c == '[') { // [ 将之前的字符串和倍数入栈保存 cStack.push(res); iStack.push(num); res = ""; num = 0; } else if( c == ']' ) { // ] 用数字栈顶数字来倍化 [] 中的元素 String tmpRes = res; final int repeat = iStack.pop() - 1; for(int i = 0; i < repeat; i++ ) { tmpRes = tmpRes + res; } res = cStack.pop() + tmpRes; //加上 数字前面的字符串 没有就是 "" } else { res = res + c; } } return res; } }
递归
class Solution(object):
def decodeString(self, s):
"""
:type s: str
:rtype: str
"""
if not s:
return ''
def helper(s, start):
tmpnum = 0
index = start
r = ''
while index < len(s):
if ord('0') <= ord(s[index]) <= ord('9'):
tmpnum = tmpnum*10 + int(s[index])
index += 1
elif s[index] == '[':
tmpr, location = helper(s, index+1)
r += tmpnum * tmpr
index = location + 1
tmpnum = 0
elif s[index] == ']':
return r, index
else:
r += s[index]
index += 1
return r
return helper(s, 0)
时间复杂度 O(n) 空间复杂度 O(n)
https://leetcode-cn.com/problems/decode-string/
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
示例 2:
输入:s = "3[a2[c]]"
输出:"accaccacc"
示例 3:
输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"
示例 4:
输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"
JavaScript Code:
/**
* @param {string} s
* @return {string}
*/
const decodeString = (s) => {
let numStack = []; // 存倍数的栈
let strStack = []; // 存 待拼接的str 的栈
let num = 0; // 倍数的“搬运工”
let result = ''; // 字符串的“搬运工”
for (const char of s) { // 逐字符扫描
if (!isNaN(char)) { // 遇到数字
num = num * 10 + Number(char); // 算出倍数
} else if (char == '[') { // 遇到 [
strStack.push(result); // result串入栈
result = ''; // 入栈后清零
numStack.push(num); // 倍数num进入栈等待
num = 0; // 入栈后清零
} else if (char == ']') { // 遇到 ],两个栈的栈顶出栈
let repeatTimes = numStack.pop(); // 获取拷贝次数
result = strStack.pop() + result.repeat(repeatTimes); // 构建子串
} else {
result += char; // 遇到字母,追加给result串
}
}
return result;
};
利用栈匹配括号,提取需要重复的元素和需要重复的次数
function decodeString(s: string): string {
let result = []
for (let i = 0; i < s.length; i++) {
const c = s[i]
if (c === ']') {
let repeatSt = ''
let repeatCnt = ''
while (result[result.length - 1] !== '[') {
repeatSt = result.pop() + repeatSt
}
result.pop()
while (/\d/.test(result[result.length - 1])) {
repeatCnt = result.pop() + repeatCnt
}
result.push(...repeatSt.repeat(~~repeatCnt));
} else {
result.push(c);
}
}
return result.join('');
};
时间 O(n) 空间 O(n)
I use two stacks to store the multiples in front of the [ while the other does the same job on the letters called numStack and strStack. When it gets the [, numbers in front of it should be push into the first stack while the letters are pushed into the other. When it meets ], it's time to construct the result with the former elements stored.
Code
var decodeString = function(s) {
let numStack = [];
let strStack = [];
let num = 0;
let res = '';
for (const char of s) {
if (!isNaN(char)) {
num = num * 10 + Number(char);
} else if (char == '[') {
strStack.push(res);
res = '';
numStack.push(num);
num = 0;
} else if (char == ']') {
let Times = numStack.pop();
res = strStack.pop() + res.repeat(Times);
} else {
res += char;
}
}
return res;
};
Time: O(n)
Space:O(n)
思路 利用栈提取处数字和字母 代码
public String decodeString(String s) {
Stack<Integer> numstack = new Stack<>();
Stack<String> strstack = new Stack<>();
String res = "";
int num = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
} else if (c == '[') {
numstack.push(num);
strstack.push(res);//将未遇到[之前的字母加入栈,同时也可以防止stack出现空栈出栈异常问题,用来存放上一次解码的数据
num = 0;
res = "";//置空后的res用于存储[]内的字符串
} else if (Character.isLetter(c)) {
res += c;
} else if (c == ']') {
String temp = "";
int count = numstack.pop();
for (int j = 0; j < count; j++) {
temp = temp + res;
}
res = strstack.pop() + temp;//strstack用于存储上次解码后的结果
}
}
return res;
}
复杂度
有思路,写不出,还需要再研究一下
class Solution:
def decodeString(self, s: str) -> str:
num_stack = []
num_val = 0
result = ""
for ele in s:
if ele.isdigit():
num_val = num_val * 10 + int(ele)
elif ele == "[":
num_stack.append([result, num_val])
result, num_val = "", 0
elif ele == "]":
top = num_stack.pop()
result = top[0] + result * top[1]
else:
result += ele
return result
利用栈处理数字、字母、括号
class Solution {
public String decodeString(String s) {
Deque<Integer> numStack = new LinkedList<>();
Deque<String> wordStack = new LinkedList<>();
StringBuilder curr = new StringBuilder();
int multi = 0;
for (char c : s.toCharArray()) {
if (c <= '9' && c >= '0') {
multi = multi * 10 + c - '0';
} else if (c == '[') {
wordStack.push(curr.toString());
numStack.push(multi);
multi = 0;
curr = new StringBuilder();
} else if (c == ']') {
int count = numStack.pop();
StringBuilder tmp = new StringBuilder(wordStack.pop());
for (int i = 0; i < count; i++) {
tmp.append(curr);
}
curr = tmp;
} else {
curr.append(c);
}
}
return curr.toString();
}
}
利用字符串栈、数字栈和拼接的字符串来接,遍历每一个字符
function decodeString(s) {
let strStack = [];
let numStack = [];
let num = 0;
let result = '';
for (const char of s) {
if (!Number.isNaN(char)) {
num = Number(char);
} else if (char === '[') {
strStack.push(result);
result = '';
numStack.push(num);
num = 0;
} else if (char === ']') {
result = strStack.pop() + result.repeat(numStack.pop());
} else {
result += char;
}
}
return result;
} ;
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c == ']':
repeatcount = ''
repeatstr = ''
while stack[-1] != '[':
repeatstr = stack.pop() + repeatstr
stack.pop()
while stack and stack[-1].isnumeric():
repeatcount = stack.pop() + repeatcount
stack.append(int(repeatcount) * repeatstr)
else:
stack.append(c)
return ''.join(stack)
class Solution(object):
def decodeString(self, s):
"""
:type s: str
:rtype: str
"""
stack, res, multi = [], "", 0
for c in s:
if c == '[':
stack.append([multi, res])
res, multi = "", 0
elif c == ']':
cur_multi, last_res = stack.pop()
res = last_res + cur_multi res
elif '0' <= c <= '9':
multi = multi 10 + int(c)
else:
res += c
return res
栈、括号匹配
遇到左括号就进行压栈处理,遇到右括号就弹出栈
性能不太行,晚点优化
Java Code:
public String decodeString(String s) {
Stack<Integer> countStack = new Stack();
Stack<String> StrStack = new Stack();
String count = "";
String str = "";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= '0' && c <= '9') {
// 遇到数字就记录 也可以用这个来判断是否数字: if (Character.isDigit(c)) {
count += Integer.parseInt(String.valueOf(c));
} else if (c == '[') {
// 遇到左括号就入栈
countStack.push(Integer.parseInt(count));
StrStack.push(str);
count = str = "";
} else if (c == ']') {
// 遇到右括号就出栈
Integer c1 = countStack.pop();
String temp = "";
for (int j = 0; j < c1; j++) {
temp += str;
}
str = StrStack.pop() + temp;
} else {
// 记录字母
str += c;
}
}
return str;
}
复杂度分析
394. 字符串解码 - 力扣(LeetCode) (leetcode-cn.com)
分为四种情况,数字,字母,[ 和 ]时候分别讨论
当为数字时候,可能为连续的数字的情况要考虑到
class Solution {
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
int multi = 0;
LinkedList<Integer> stackMulti = new LinkedList<>();
LinkedList<String> stackRes = new LinkedList<>();
for(Character c :s.toCharArray()){
if(c >= '0' && c <='9'){
multi = multi*10 + Integer.parseInt(c + "");
}else if(c == '['){
stackMulti.addLast(multi);
stackRes.addLast(res.toString());
res = new StringBuilder();
multi = 0;
}else if(c == ']'){
StringBuilder tmp = new StringBuilder();
int curMulti = stackMulti.removeLast();
for(int i = 0; i < curMulti; i++){
tmp.append(res);
}
res = new StringBuilder(stackRes.removeLast() + tmp);
}else{
res.append(c);
}
}
return res.toString();
}
}
1、 遍历 s 字符串,假设当前字符为 c 2、 如果是字母的话,拼接字符 curStr = curStr + c 3、 如果是数字的话,放入到一个临时变量 curNum 4、 如果碰到"[",则将 curStr、curNum 入栈 stack,入栈之后 curStr、curNum 设为初始值 5、 如果碰到"]", 则依次出栈,分别记作 prevStr、prevNum 6、出栈的时候,拼接字符串 curStr = prevStr + curStr.repeat(prevNum);
思考: stack 里面相邻的一定是字母数字隔开的吗,有没有可能出现连续的字母或数字
JavaScript Code:
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
var curStr = "",
curNum = 0,
stack = [];
for (var i = 0; i < s.length; i++) {
var c = s.charAt(i);
if (c >= "0" && c <= "9") {
curNum = curNum * 10 + Number(c);
} else if (c === "[") {
stack.push(curNum);
stack.push(curStr);
curStr = "";
curNum = 0;
} else if (c === "]") {
let prevStr = stack.pop();
let prevNum = stack.pop();
curStr = prevStr + curStr.repeat(prevNum);
} else {
curStr += c;
}
}
return curStr
};
复杂度分析
令 n 为数组长度。
394. 字符串解码
https://leetcode-cn.com/problems/decode-string/
遍历字符串,遇到非']'就入栈, 遇到就 '[' 就出栈
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c == ']':
repeatStr = ''
repeatCount = ''
while stack and stack[-1] != '[':
repeatStr = stack.pop() + repeatStr
# pop 掉 "["
stack.pop()
while stack and stack[-1].isnumeric():
repeatCount = stack.pop() + repeatCount
stack.append(repeatStr * int(repeatCount))
else:
stack.append(c)
return "".join(stack)
394. 字符串解码
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/decode-string/
前置知识
题目描述
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = "3[a]2[bc]" 输出:"aaabcbc" 示例 2:
输入:s = "3[a2[c]]" 输出:"accaccacc" 示例 3:
输入:s = "2[abc]3[cd]ef" 输出:"abcabccdcdcdef" 示例 4:
输入:s = "abc3[cd]xyz" 输出:"abccdcdcdxyz"