Open azl397985856 opened 3 years ago
Time Complexity: O(N) where N is the length of the decoded string. Space Complexity: O(N) where N is the length of the decoded string.
Language: Java
public String decodeString(String s) {
Deque<Character> stack = new ArrayDeque<>();
for (char c : s.toCharArray()) {
if (c != ']') {
stack.addFirst(c);
continue;
}
List<Character> decodedStr = new ArrayList<>();
while (stack.peekFirst() != '[') {
decodedStr.add(stack.removeFirst());
}
// Remove '['
stack.removeFirst();
// Get multiplier
int num = 0;
int base = 1;
// Important to check if stack is empty first
while (!stack.isEmpty() && Character.isDigit(stack.peekFirst())) {
// It is very important to keep track of base, as the lower digits may be 0s like "100"
// Simply using num = num * 10 + stack.removeFirst() - '0' won't work.
num = num + (stack.removeFirst() - '0') * base;
base *= 10;
}
// Put decoded string back to stack
for (int i = 0; i < num; i++) {
for (int j = decodedStr.size() - 1; j >= 0; j--) {
stack.addFirst(decodedStr.get(j));
}
}
}
char[] result = new char[stack.size()];
for (int i = stack.size() - 1; i >= 0; i--) {
result[i] = stack.removeFirst();
}
return new String(result);
}
# use stack to store a pair number of times + the string to repeat
# use currCount to store how many times to repeat current substring
# use currString to store current string iterated so far
class Solution:
def decodeString(self, s: str) -> str:
currString = ''
currCount = 0
stack = []
for char in s:
if char.isdigit():
currCount = currCount * 10 + int(char)
elif char == '[':
# start of a new subtring
# store currCount and string
# reset currCount and string
stack.append(currString)
stack.append(currCount)
currString = ''
currCount = 0
elif char == ']':
# end of this substring
# pop stack top string pair and add to current String
count = stack.pop()
string = stack.pop()
currString = string + count * currString
else:
currString += char
return currString
思路 遇到数字执行10进制的数字计算,前一个比后一个多10倍 遇到[进行压栈处理 遇到]进行出站处理 遇到普通字符,加上就行 代码
class Solution {
public:
string decodeString(string s) {
int num = 0;
string str = "";
string res = "";
stack<int> numstack;
stack<string> strstack;
int len = s.size();
for(int i = 0;i < len; i++)
{
if(s[i]>='0' && s[i]<='9')
{
num = 10*num + s[i] -'0';
}
else if(s[i]=='[')
{
numstack.push(num);
strstack.push(str);
num = 0;
str = "";
}
else if(s[i]==']')
{
int j = numstack.top();
numstack.pop();
for(int k = 0;k < j;k++ )
{
strstack.top() += str;
}
str = strstack.top();
strstack.pop();
}
else
{
str +=s[i];
}
}
return str;
}
};
复杂度 时间复杂度遍历s,同时遍历里面重复[]的次数,复杂度为O(NUM的和) 空间复杂度O([]里的lenth*num)
Pairing brackets in a string is often associated with stack ADT. We do nothing but pushing each char onto a stack until we encounter the right bracket ']'. When ']' is found, we need to pop elements on the stack until we find its first pairing bracket '['. Then some operations need to be done with the popped elements, in this case, we record the chars in between '[' and ']', and use the knowledge of numeric number right before '[' to repeat the recorded chars. After the operation is done, we can remove the pairing bracket '[' and the numeric number from the stack and push the after-processing chars back to the stack. After iterating through the original string, the stack will be left of pure chars without numeric numbers and brackets. The final results is done backward iterating through the stack.
The key point in implementing it in c++ is that the stack is of type char not string, because char comparison is cheaper than the string comparison.
One caveat when we get the numeric number from the stack is that we need an additional stack to store the digits. This is because we store the number from high digit to low digit, for example, if we have 300[a], the stack is ['3', '0', '0', '[', 'a'], we need to have a helper stack to store the digits ['0', '0', '3']. An optimization can be done by observing that all integers are in the range [1, 300]. We can allocate a static array of size 3 and reset it to ['*', '*', '*'] before we compute the numeric number and fill the digits backwards into the array.
This is a more natural solution to me and sounds like DFS. The two stacks approach consisting of numeric number stack and string stack is kind of hard to memorize for me.
class Solution
{
public:
string decodeString(string s)
{
std::stack<char> resStack;
std::vector<char> digitVec(3, '*');
for (auto const& c : s) {
if (c != ']') {
resStack.push(c);
} else {
// Find the chars to be repeated in between '[' and ']'
std::vector<char> repeatStrVec;
while (resStack.top() != '[') {
repeatStrVec.push_back(resStack.top());
resStack.pop();
}
// Remove the '[' from the stack
resStack.pop();
// Find the repeat count, and remove the numbers from the stack
std::fill(digitVec.begin(), digitVec.end(), '*');
int idx = digitVec.size();
// static_cast is needed as isdigit has undefined behavior for char type
while (!resStack.empty() && std::isdigit(static_cast<unsigned char>(resStack.top()))) {
digitVec[--idx] = resStack.top();
resStack.pop();
}
int count{digitVec[idx] - '0'};
for (int ii = idx+1; ii < digitVec.size(); ii++) {
count = 10 * count + digitVec[ii] - '0';
}
// Repeat the chars in betwen '[' and ']' count times and push them back to the stack
for (int ii = 0; ii < count; ii++) {
for (auto it = repeatStrVec.rbegin(); it != repeatStrVec.rend(); it++) {
resStack.push(*it);
}
}
}
}
// Pre-allocate the string so that we don't need string concatenation
std::string res(resStack.size(), '*');
int idx = resStack.size();
while (!resStack.empty()) {
res[--idx] = resStack.top();
resStack.pop();
}
return res;
}
};
import (
"fmt"
"strconv"
"strings"
)
func decodeString(s string) string {
stk := []string{}
ptr := 0
for ptr < len(s) {
cur := s[ptr]
if cur >= '0' && cur <= '9'{
digits := getDigis(s, &ptr)
stk = append(stk, digits)
} else if (cur >= 'a' && cur <= 'z' || cur >= 'A' && cur <='Z' || cur =='['){
stk = append(stk, string(cur))
ptr++
} else {
ptr ++
sub := []string{}
for stk[len(stk) - 1] != "[" {
sub = append(sub, stk[len(stk) - 1])
stk = stk[:len(stk)-1]
}
for i := 0; i < len(sub)/2; i++{
sub[i], sub[len(sub) -i - 1] = sub[len(sub) -i -1], sub[i]
}
stk = stk[:len(stk) - 1]
repTime, _ := strconv.Atoi(stk[len(stk) -1])
stk = stk[: len(stk) - 1]
t := strings.Repeat(getString(sub), repTime)
stk = append(stk, t)
}
}
return getString(stk)
}
func getDigis(s string, ptr *int) string {
ret := ""
for ; s[*ptr] >= '0' && s[*ptr] <= '9'; *ptr++{
ret += string(s[*ptr])
}
return ret
}
func getString(v []string) string {
ret := ""
for _, s := range v {
ret += s
}
return ret
}
这道题因为有“[”“]”, 所以我第一时间想到的是用stack(LIFO)。 我们能遍历整个字符串来看如何处理每个字符
count
的字符串内ans
的字符串内count
和ans
入栈,这里入栈是因为ans
代表了当前'['外层我们想要的字符串,count则表示[
内层需要重复的次数。入栈后当前ans
和count
清空ans
更新为原ans+重复次数*ans
class Solution:
def decodeString(self, s: str) -> str:
stack = []
ans = ""
count = ""
for char in s:
if "0" <= char <= "9":
count += char
elif "a" <= char <= "z":
ans += char
elif char == "]":
pair = stack.pop()
ans = pair[1]+ int(pair[0])*ans
#count = ""
elif char == "[":
stack.append((count, ans))
count = ""
ans = ""
return ans
Time Complexity: O(n) 遍历整个字符串 Space complexity: O(n) 最多有可能创建一个 n 长度的stack
class Solution {
public String decodeString(String s) {
Stack<String> stack = new Stack<>();
Stack<Integer> numStack = new Stack<>();
StringBuilder res = new StringBuilder();
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);
num = 0;
stack.push(res.toString());
res = new StringBuilder();
}else if(c == ']'){
StringBuilder tmp = new StringBuilder(stack.pop());
int rep = numStack.pop();
for (int k = 0; k < rep; k++){
tmp.append(res);
}
res = tmp;
}else {
res.append(c);
}
}
return res.toString();
}
}
Time Complexity: O(n) Space Complexity: O(n)
两个栈,一个字母栈,一个数字栈 左括号开始就进入字母栈,右括号就开始出栈(出栈生成的结果要重新入字母栈),括号也要进栈,标志边界
# b:[ a [ c ] -> b:[ a c c ] -> b:a c c a c c a c c
# res: a c c a c c a c c
# a:3 -> a:2 -> a:
# b:[ a ] -> b:a a a [ b c ] -> b:a a a b c b c
# res:
class Solution:
def decodeString(self, s: str) -> str:
'''
case: "100[leetcode]"
'''
stack_num = []
stack_alpha = []
flag = False
for i in range(len(s)):
cur = s[i]
if cur.isdigit():
if flag is False:
stack_num.append(int(cur))
else:
pre = int(stack_num.pop())
num = pre * 10 + int(cur)
stack_num.append(num)
flag = True
elif cur == ']':
flag = False
word = ''
while len(stack_alpha) > 0:
tmp = stack_alpha.pop()
if tmp == '[':
break
word += tmp
# 逆序退出栈
count = int(stack_num.pop())
while count > 0:
# for ele in word:
for j in range(len(word) - 1, -1, -1):
stack_alpha.append(word[j])
count -= 1
else:
flag = False
stack_alpha.append(cur)
if len(stack_num) != 0:
return ''
return ''.join(stack_alpha)
时间复杂度:o(n) 空间复杂度:o(n)
通过两个数组维护数字栈和字符串栈
var decodeString = function (s) {
let numList = [];//存放数字
let numStr = '';//存放数字长度
let stackList = [];//存放字符串
let str = '';//存放括号里面的字符串
let result = '';//返回值
for (let i = 0; i < s.length; i++) {
const n = s.charAt(i);
if (n >= 0 && n <= 9) {
numStr += n;
} else if (n === '[') {//这时说明前面数字,字符串已经匹配完了
numList.push(numStr);
stackList.push(str);
numStr = '';
str = '';
} else if (n === ']') {
const num = numList.pop();
let t = '';
for (let j = 0; j < num; j++) {
t += str;
}
//已经计算了一个闭环,就要判断stackList中还存不存在字符串,存在就加,例如:3[a2[c]]=>3[acc]
let temp = stackList.length > 0 ? stackList.pop() : '';
str = temp + t;
//如果当前数字数组中没有数据了,那就说明当前位置已经没有可以重复的字符串了,直接加入到返回值里面
if (numList.length === 0) {
result += str;
str = '';
}
} else {
//如果当前数字数组中没有数据了,那就说明当前位置已经没有可以重复的字符串了,直接加入到返回值里面
if (numList.length === 0) {
result += n;
} else {
str += n;
}
}
}
return result;
};
这题看着容易, 但是实现好不容易。
首先弄两个 stack, 其中一个存数字, 另一个存string。 然后每次遇到 ']' 的时候就把string 中最后一个替换成 数字stack[-1]* str_stack[-1].
class Solution:
def decodeString(self, s):
stack_num, stack_string = [],[""]
num = 0
res = ''
for c in s:
if c.isdigit():
num = num*10 + int(c)
elif c =='[':
stack_string.append("")
stack_num.append(num)
num = 0
elif c == ']':
temp_str = stack_string.pop()
temp_rep = stack_num.pop()
last_str = stack_string.pop()
stack_string.append(last_str+ temp_rep*temp_str)
else:
stack_string[-1] += c
return "".join(stack_string)
遇到'['时,栈内保存当前子串和倍数。遇到']'时,弹出栈顶并与当前子串组合。
class Solution:
def decodeString(self, s: str) -> str:
stack = []
ans = ''
num = 0
for c in s:
if '0' <= c <= '9':
# 注意数字位数
num = num*10 + int(c)
elif c == '[':
stack.append((num, ans))
ans = ''
num = 0
elif c == ']':
cnt, tmp_str = stack.pop()
ans = tmp_str + ans*cnt
else:
ans += c
return ans
复杂度
结果需要从括号内向外逐层解开,使用栈可以达到我们的目标。最后在栈内的字符串都是解好的字符串,连起来返回即可。
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c == ']':
mul = ''
tmp = ''
while stack and stack[-1] != '[':
tmp = stack.pop() + tmp. # 在前面pop后面就不用翻转了
stack.pop()
while stack and stack[-1].isdigit():
mul = stack.pop() + mul
tmp = tmp * int(mul)
stack.append(tmp)
else:
stack.append(c)
return ''.join(stack)
时间:O(N),N为s长度 空间:O(N)
class Solution {
//c为数字:转化为数字num
//c为字母:在res尾部添加c
//c为‘[’:将当前num和res入栈stack,并将两者分别空置
//c为‘]’:stack出栈,res = 刚出栈的res + 当前res * 刚出栈的数字num
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
int num = 0;
LinkedList<Integer> stackNum = new LinkedList<>();
LinkedList<StringBuilder> stackRes = new LinkedList<>();
for(Character c : s.toCharArray()){
if(c >= '0' && c <= '9'){
num = num * 10 + c - '0';
}else if(c == '['){
stackNum.addLast(num);
stackRes.addLast(res);
num = 0;
res = new StringBuilder();
}else if(c == ']'){
int curNum = stackNum.removeLast();
StringBuilder tmp = new StringBuilder();
for(int i = 0; i < curNum; i++){
tmp.append(res);
}
res = stackRes.removeLast();
res.append(tmp);
}else{
res.append(c);
}
}
return res.toString();
}
}
时间复杂度:O(N) 空间复杂度:O(N)
/**
* @param {string} s
* @return {string}
*/
var decodeString = function (s) {
let num = 0;
let numStock = []
let resultStock = []
let result = ''
for (let str in s) {
if (!isNaN(s[str])) {
num = num * 10 + Number(s[str])
} else if (s[str] == '[') {
resultStock.push(result);
result = '';
numStock.push(num)
num = 0;
} else if (s[str] == ']') {
let copyNum = numStock.pop();
result = resultStock.pop() + result.repeat(copyNum);
} else {
result += s[str]
}
}
return result
};
console.log(decodeString('3[a]2[bc]'))
时间复杂度:O(N) 空间复杂度:O(N)
时间复杂度O(n) 空间复杂度O(n)
class Solution {
public:
string decodeString(string s) {
string res; // 字符串形式的栈
for (int i = 0; i < s.size(); i++) { // 遍历整个string
if (s[i] != ']') {
res += s[i];
}
else if (s[i] == ']') { // 如果到']'就往回走
string saveStr = ""; // 每次循环初始化
string saveNum = "";
while (res.back() != '[') { // 前面一定有'['
saveStr = res.back() + saveStr; // 记录括号内的字符串
res.pop_back(); // 往前走
}
res.pop_back(); // 去掉'['
while (res.size() != 0 && isdigit(res.back())) { // 前面是数字且不越界都成立才循环
saveNum = res.back() + saveNum; // 记录前面的数字
res.pop_back(); // 往前走
} // 得到数字和数字作用的字符串,已解出当前括号
int n = stoi(saveNum);
while (n--) {
res += saveStr;
}
}
}
return res;
}
};
Problem Link
Ideas
stack[-1] != '[':
is required to avoid [ in the string.Complexity:
Code
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c ==']':
string_to_repeat = ''
repeat_times = ''
while stack and stack[-1] != '[':
string_to_repeat =stack.pop() + string_to_repeat
stack.pop() #pop out [
while stack and stack[-1].isnumeric():
repeat_times = stack.pop() + repeat_times
stack.append(string_to_repeat * int(repeat_times))
else:
stack.append(c)
return ''.join(stack)
https://leetcode-cn.com/problems/decode-string/
该问题需要由内向外扩展,很明显可以用到stack先进后出的特性。 具体到问题上来,我们新创建额外两个stack,一个用来存数字,一个用来存字母。当遇到数字时,将数字记录下来为multi(要记得处理连续数字的情况);当遇到字母时,直接append到res;当遇到'[\' 符号时,将当前的res和multi压入各自的stack中,并且将multi和res初始化;当遇到']\'时,需要初始化一个tmp变量,pop出multi里的数字,并迭代加入res到tmp中去,最后要将结果初始为tmp + res.pop()。
class Solution {
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
Stack<Integer> numberStack = new Stack();
Stack<String> stringStack = new Stack();
int multi = 0;
for(Character c : s.toCharArray()) {
if(c == '[') {
numberStack.push(multi);
stringStack.push(res.toString());
multi = 0;
res = new StringBuilder();
} else if(c == ']') {
StringBuilder tmp = new StringBuilder();
int curMulti = numberStack.pop();
for(int i = 0; i < curMulti; i++) {
tmp.append(res);
}
res = new StringBuilder(stringStack.pop() + tmp);
} else if(c >= '0' && c <= '9') {
multi = multi * 10 + Integer.parseInt(c + "");
} else {
res.append(c);
}
}
return res.toString();
}
}
O(n)
O(n)
9.13 day3 394.字符串解码
思路:
解码的过程是以找到成对的括弧,重复中间的字符。括弧可用先进后出特性的栈表示
遍历S中的字符,如果不是']'重复压栈操作,如果是']'时,说明括弧匹配时候,只要栈最后一位不为'['时,继续取出刚入栈的,作为重复字符串,并执行出栈。在判断栈中倒末是否为数字,是数字则进行数字与重复字符的运算,并添加到栈中。
def decode_string(s):
stack = []
for c in s :
if c == ']':
repeatStr = ''
repeatCount = ''
while stack and stack[-1]!='[': #括弧匹配时候把重复的字符取出来
repeatStr = stack.pop()+ repeatStr #取出来的字符就出栈
stack.pop() #把'['也出栈
while stack and stack[-1].isnumeric():
repeatCount = stack.pop()+repeatCount #判断是否数值时候把数字取出来,数字出栈
stack.append(int(repeatCount) *repeatStr) #按数字重复字符,并加到append
else:
stack.append(c) #没有遇到]前持续压栈
return "".join(stack) #把stack重新拼接
复杂度分析:
class Solution:
def decodeString(self, s: str) -> str:
stack =[]
res = ''
k = 0
for elem in s:
if '0' <= elem <= '9':
k = k*10+ int(elem)
elif elem == '[':
stack.append([res, k])
res = ''
k =0
elif elem == ']':
tmp_str, tmp_k = stack.pop()
res = tmp_str + res * tmp_k
else:
res = res + elem
return res
time:O(N)
space(O(N))
In this question, the encoded string is composed by two parts: string cascading and sub-string in the brackets.
To cascade a string, use a while loop to scan all the components in the input s and use a StringBuilder
to record all the decoded part.
To properly decode the sub-string in the bracket, we use a recursion that keep decoding the inner brackets and finally return a decoded sub-string. Then duplicate the decoded-substring according to the leading number.
Use stack to locate the matching open bracket and close bracket.
The Java API involved:
s.indexOf(char c, int i )
find the index of c
in a string stating from the index i
s.substring(int s, int e)
s is included; e is excludedInteger.parseInt(str s)
convert a string to int class Solution {
public String decodeString(String s) {
StringBuilder sb = new StringBuilder();
int len = s.length();
int i = 0;
while(i < len){
char c = s.charAt(i);
if(c-'a' >= 0 && c-'z' <= 0){
sb.append(c);
i++;
}else if(c-'0' >= 0 && c -'9' <= 0){
//find the first open bracket
int strt = s.indexOf("[",i);
int end = findEnd(strt, len, s);
String mids= s.substring(strt+1, end);
String subs = decodeString(mids);
//find the number
String numstr = s.substring(i,strt);
int num = Integer.parseInt(numstr);
for(int j = 0; j < num ;j++){
sb.append(subs);
}
i = end+1;
}
}
return sb.toString();
}
private int findEnd(int strt, int len, String s){
Deque<Character> brkt = new ArrayDeque<>();
brkt.push(s.charAt(strt));
for(int i = strt+1; i <= len ; i++){
char c = s.charAt(i);
if(c == '[')
brkt.push(c);
else if( c == ']')
brkt.pop();
if(brkt.peek() == null)
return i;
}
return -1;
}
}
Runtime: 0 ms, faster than 100.00% of Java online submissions for Decode String.
Memory Usage: 36.9 MB, less than 84.66% of Java online submissions for Decode String.
Time: O(N)
Space: O(N) for the stack
python
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c == ']':
stri = ""
cnt = ""
while stack and stack[-1] != '[':
stri = stack.pop() + stri
stack.pop()
while stack and stack[-1].isnumeric():
cnt = stack.pop() + cnt
stack.append(stri * int(cnt))
else:
stack.append(c)
return "".join(stack)
function decodeString(s: string): string {
const stack = []
let str = ''
let num = ''
for(const i of s){
if(!isNaN(+i)){
num += i
} else if( i === '['){
stack.push(+num)
num = ''
stack.push(i)
} else if( i === ']'){
str = ''
while( stack[stack.length - 1] !== '['){
// 注意顺序
str = stack.pop() + str
}
// stack[stack.length - 1] === '['
stack.pop()
stack.push(str.repeat(stack.pop()))
} else {
stack.push(i)
}
}
return stack.join('');
};
var decodeString = function (s) {
let strStack = [];
let numStrack = [];
let tempNum = 0;
for (let i of s) {
if (!isNaN(i)) {
tempNum = tempNum * 10 + +i;
} else if (i === "]") {
let str = "";
let cur = strStack.pop();
let repeat = numStrack.pop();
while (cur && cur !== "[") {
str = cur + str;
cur = strStack.pop();
}
str = str.repeat(repeat);
strStack.push(str);
} else {
strStack.push(i);
if (tempNum) {
numStrack.push(tempNum);
tempNum = 0;
}
}
}
return strStack.join("");
};
时间 O(n) 空间 O(n)
思路
使用字符栈与数字栈,遇到 [ 就进栈 遇到 ] 就出栈,出栈时将字符栈,数字栈同时出栈并运算。还需要考虑数字的进位问题 ret变量缓存着从栈底弹出字符串总和,并且有将字符串压入栈底的作用
代码
class Solution {
public String decodeString(String s) {
Stack<String> stacks = new Stack<>();
Stack<Integer> nums = new Stack<>();
String ret = "";
int num = 0;
for (char c : s.toCharArray()){
if ('0' <= c && c <= '9'){
num=num*10+c-'0';
}else if('a' <= c && c <= 'z'){
ret += c;
}else if (c == '['){
stacks.push(ret);
nums.push(num);
ret = "";
num = 0;
}else {
Integer cur = nums.pop();
String stackTemp = stacks.pop();
for (int i = 0; i < cur; i++) {
stackTemp += ret;
}
ret = stackTemp;
}
}
return ret;
}
}
复杂度
时间复杂度:O(N)
空间复杂度:O(N)
class Solution {
public String decodeString(String s) {
char[] c = s.toCharArray();
int l = c.length;
Stack
Naturally, we can think of using stack to solve this problem, we start push to then stack when we see a digit and start pop the stack when we see the ']', untill we see the '[' at that point we save all the chars between '[' and ']' into a temp string, we then popup the digit from the stack and add them into the result. the only issue is when the encoded string itself is enbeded with another encoded string. To solve this, we can so a small modification to the stack, after we decode the string using the stack, we check if the stack is NULL,
class Solution {
public:
string decodeString(string s) {
string result;
stack<char> encodingStack;
bool isPush = false;
for (char c : s) {
if (isdigit(c) || (isPush && c != ']')) {
isPush = true;
encodingStack.push(c);
} else if (c == ']') {
isPush = false;
string tmp;
while (!encodingStack.empty() && encodingStack.top() != '[') {
tmp.push_back(encodingStack.top());
encodingStack.pop();
}
// pop out '['
encodingStack.pop();
reverse(tmp.begin(), tmp.end());
string numStr;
while (!encodingStack.empty() && isdigit(encodingStack.top())) {
numStr.push_back(encodingStack.top());
encodingStack.pop();
}
reverse(numStr.begin(), numStr.end());
// pop out num
int num = stoi(numStr);
string addition;
for (int i = 0; i < num; i++) {
addition.append(tmp);
}
if (encodingStack.empty())
result.append(addition);
else {
for (char ch : addition)
encodingStack.push(ch);
isPush = true;
}
} else {
result.push_back(c);
}
}
return result;
}
};
O((maxK to the power of countK)* n): countK is the maximum nested level and maxK is the maximum value of K.
O((maxK to the power of countK)* n)
import java.util.*;
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()) {
if (Character.isDigit(s.charAt(idx))) {
int count = 0;
while (Character.isDigit(s.charAt(idx))) {
count = 10 * count + (s.charAt(idx) - '0');
idx++;
}
countStack.push(count);
}
else if (s.charAt(idx) == '[') {
resStack.push(res);
res = "";
idx++;
}
else if (s.charAt(idx) == ']') {
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;
}
}
时间复杂度O(N) 空间复杂度O(N)
想法是使用栈来进行字符串的复制工作,但是我参考了leetcode的官方的思路,使用了两个栈,一个栈是用来存储数字,另一个用来存储字符串。
如果是 ' ] ',这时候比较关键,因为这时候的字符串变量是有值的,这个值是括号里面的值。因此我们需要复制这个字符串变量的值k次,然后依次出栈。
class Solution {
public:
string decodeString(string s) {
stack<int> nums;
stack<string> strs;
string res = "";
int n = 0;
for (int i = 0; i < s.size(); i ++) {
if (s[i] >= '0' && s[i] <= '9') {
n = n * 10 + (s[i] - '0');
} else if (s[i] == '[') {
nums.push(n);
n = 0;
strs.push(res);
res = "";
} else if (s[i] >= 'a' && s[i] <= 'z' || s[i] >= 'A' && s[i] <= 'Z') {
res += s[i];
} else {
int time = nums.top();
nums.pop();
for (int j = 0; j < time; j ++) {
strs.top() += res;
}
res = strs.top();
strs.pop();
}
}
return res;
}
};
# python
class Solution(object):
def decodeString(self, s):
"""
:type s: str
:rtype: str
"""
stack = []
for w in s:
repeat_ct = ""
repeat_char = ""
if w == "]":
while stack[-1] != '[':
repeat_char = stack.pop() + repeat_char
stack.pop() # delete [
while stack and stack[-1].isnumeric():
repeat_ct = stack.pop() + repeat_ct
temp = int(repeat_ct)*repeat_char
stack.append(temp)
else:
stack.append(w)
return "".join(stack)
时间复杂度: O(s) 空间复杂度: O(s)
遇到非]进栈,遇到]就出栈,遇到[前将出栈的拼成一个字符串,然后[之前的所有数字都出栈拼成重复次数,按照重复次数重复前面拼成的字符串,拼成的结果再放到栈里去,最终结果就是栈里的各个项拼成的字符串
var decodeString = function (s) {
const stack = [];
for (let i = 0; i < s.length; i++) {
switch (s[i]) {
case "]": {
let str = "";
while (stack[stack.length - 1] !== "[") {
str = stack.pop() + str;
}
stack.pop();
let number = 0,
count = 0;
while (stack[stack.length - 1] >= 0 && stack[stack.length - 1] <= 9) {
number = number + stack.pop() * Math.pow(10, count++);
}
let sum = "";
while (number > 0) {
sum += str;
number--;
}
stack.push(sum);
break;
}
default: {
if (Number(s[i]) >= 0 && Number(s[i]) <= 9) {
stack.push(Number(s[i]));
} else {
stack.push(s[i]);
}
}
}
}
return stack.join("");
};
遇到[就把前面的字符串和数字压入stack,存储当前[]内的字符,直到遇见],则弹出stack,把重复次数的当前字符增加在前字符后面
class Solution:
def decodeString(self, s: str) -> str:
k_number = 0
resultString = ""
decoded_string = []
for char in s:
if char.isnumeric():
k_number = 10 * k_number + int(char)
elif char == "[":
decoded_string.append(resultString)
decoded_string.append(k_number)
k_number = 0
resultString = ""
elif char == "]":
current_k = decoded_string.pop()
currentString = decoded_string.pop()
resultString = currentString + current_k * resultString
else:
resultString += char
return resultString
时间复杂度:O(N)
空间复杂度:O(N)
using stack to keep track result, iterate each element into stack, if you see "]", start to pop until you see the "[".
class Solution:
def decodeString(self, s: str) -> str:
stack=[]
for e in s:
if e=="]":
temp=[]
while stack[-1] != "[":
temp.append(stack.pop())
stack.pop()
count=0
order=1
while stack and stack[-1].isnumeric():
count+=int(stack.pop())*order
order*=10
for i in range (count):
stack.extend(temp[::-1])
else:
stack.append(e)
return "".join(stack)
T: O(n) S: O(n)
思路: 遇到】之前一直进栈, 遇到】之后开始出栈解码string,重复的string再依次进栈。 Python 3 code:
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for char in s:
if char != ']':
stack.append(char)
else:
cur_str = ''
itr_iter = ''
while stack and stack[-1] != '[':
cur_str = stack.pop() + cur_str
stack.pop()
while stack and stack[-1].isdigit():
str_iter = stack.pop() + str_iter
int_iter = int(str_iter)
stack.append(cur_str * int_iter)
return ''.join(stack)
Time complexity: O(N) N = length of decoded string Space Complexity: O(N)
function decodeString(s: string): string {
let stack: string[] = [], i = 0, length = s.length, res = ''
while(i < length) {
if(s[i] === ']') {
let str = '', time: string | number = '', t = ''
while(stack[stack.length - 1] !== '[') {
str = stack.pop() + str
}
stack.pop()
while(stack.length && stack[stack.length - 1].charCodeAt(0) >= '0'.charCodeAt(0) && stack[stack.length - 1].charCodeAt(0) <= '9'.charCodeAt(0)) {
time = stack.pop() + time
}
stack.push(str.repeat(+time))
} else {
stack.push(s[i])
}
i++
}
return stack.join('')
};
没有思路,把答案默写了一遍
python代码
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for i in s:
if i == ']':
strs = ''
repeat_number = ''
while stack and stack[-1] !='[':
strs = stack.pop()+strs
stack.pop() #pop out'[]'
while stack and stack[-1].isdigit():
repeat_number = repeat_number + stack.pop()
stack.append(int(repeat_number)*strs)
else:
stack.append(i)
return "".join(stack)
复杂度分析
遍历所有的字母
如果是 [, 0-9, a-z
的情况, 直接放入栈中
如果是 ]
的情况, 说明要开始出栈找出 单词 word 和 [
前面的数字
向前pop, 每次加到 word 中 知道栈顶元素为 [
代表 word 已经全部 pop 完了
pop 一次, 将栈中的 [
pop 出
继续 pop 得到栈中的数字, 有两种情况
最后将 count * word 得到新的 string 并放入栈中
最后将栈中元素按相反顺序变成 string 即可
class Solution:
def decodeString(self, s: str) -> str:
stack = []
i = 0
for c in s:
if c == "]":
count = ''
word = ''
# get word
while stack[-1] != "[":
word = stack.pop() + word
stack.pop() # pop out [
# get num
while len(stack) > 0 and stack[-1].isdigit():
count = stack.pop() + count
stack += int(count) * word
else:
stack.append(c)
return ''.join(stack)
时间复杂度: O(n) 遍历一次单词, 栈里每个元素最多也是操作常数次
空间复杂度: O(n) 栈最大可以达到 O(n) 的大小
遍历字符串,除了"]" ,其他一律入栈(数字可能需要拼接后再入栈),遇到"]" 开始出栈,从栈顶开始出栈直到遇到"[",拼接出栈的这部分字母,再出栈一个就是这部分字母出现的次数,组合成字符串后重新入栈。最后将栈里所有字符拼接
java
class Solution {
int ptr;
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<String>();
StringBuffer ret = new StringBuffer();
ptr = 0;
while (ptr < s.length()) {
char c = s.charAt(ptr);
if(Character.isDigit(c)){
String intStr = getIntStr(s);
stk.add(intStr);
}else if(Character.isLetter(c) || c == '['){
stk.add(Character.toString(c));
ptr++;
}else{ //开始出栈
ptr++;
LinkedList<String> sub = new LinkedList<String>();
while (!"[".equals(stk.peekLast())) {
sub.add(stk.removeLast());
}
// 移除"["
stk.removeLast();
// 获得正整数
int repTime = Integer.parseInt(stk.removeLast());
Collections.reverse(sub);
StringBuffer t = new StringBuffer();
String o = getLinkedStr(sub);
while(repTime > 0){
t.append(o);
repTime--;
}
stk.add(t.toString());
}
}
return getLinkedStr(stk);
}
private String getIntStr(String s){
StringBuffer sb = new StringBuffer();
while(Character.isDigit(s.charAt(ptr))){
sb.append(s.charAt(ptr++));
}
return sb.toString();
}
private String getLinkedStr(LinkedList list){
StringBuffer sb = new StringBuffer();
for(int i = 0 ; i < list.size() ; i++){
sb.append(list.get(i));
}
return sb.toString();
}
}
时间复杂度: O(n)
空间复杂度: O(n)
stack
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for c in s:
if c == ']':
sub_s = ''
while(stack and stack[-1]!='['):
sub_s = stack.pop() + sub_s
stack.pop()
num = 0
count = 0
while(stack and stack[-1].isnumeric()):
num = num * 10 ** count + int(stack.pop())
count+=1
stack.append(sub_s*num)
print(stack)
else:
stack.append(c)
return ''.join(stack)
Space: O(N) Time: O(N)
const decodeString = function (s, i = 0) {
let letter = /[a-z]/i;
let number = /[0-9]/;
let openBracket = '[';
let closedBracket = ']';
let result = '';
let counter = '';
while (i < s.length) {
if (letter.test(s[i])) {
result += s[i];
i++;
} else if (number.test(s[i])) {
counter += s[i];
i++;
} else if (s[i] === openBracket) {
const [window, nextIndex] = decodeString(s, i + 1);
result += window.repeat(Number(counter));
counter = '';
i = nextIndex;
continue;
} else if (s[i] === closedBracket) {
return [result, i + 1];
}
}
};
1 <= s.length <= 30
s consists of lowercase English letters, digits, and square brackets '[]'.
s is guaranteed to be a valid input.
All the integers in s are in the range [1, 300].
Input: s = "3[a2[c]]"
Output: "accaccacc"
k is guaranteed to be a positive integer
you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k.
2 stacks, Stack<StringBuilder>, Stack<Integer>
k can be greater than 10
if we see digit, build the complete integer (curFreq * 10 + s.charAt(curIndex) - '0')
if we see letter, build the complete string (by curStr.append(s.charAt(curIndex));)
if we see [, push curStr and curFreq into respective stacks, reset
*if we see ],
curStr is the string to repeat
pop the top string, append the repeated string after it, it becomes the curStr
Input: s = "a3[a2[c]]e"
Output: "aaccaccacce"
c
a 2
a 3
acc
a 3
curStr: aaccaccacc
curStr: aaccaccacce
Time: O(decoded res length)
Space: O(decoded res length)
class Solution {
public String decodeString(String s) {
if (s.length() == 1) return s;
Stack<Integer> freqStack = new Stack<>();
Stack<StringBuilder> strStack = new Stack<>();
int curIndex = 0;
StringBuilder curStr = new StringBuilder();
int curFreq = 0;
while (curIndex < s.length()) {
if (Character.isLetter(s.charAt(curIndex))) {
curStr.append(s.charAt(curIndex));
}
else if (Character.isDigit(s.charAt(curIndex))) {
curFreq = curFreq * 10 + s.charAt(curIndex) - '0';
}
else if (s.charAt(curIndex) == '[') {
strStack.push(curStr);
curStr = new StringBuilder();
freqStack.push(curFreq);
curFreq = 0;
} else if (s.charAt(curIndex) == ']') { // this part needs caution
StringBuilder temp = curStr; // temp is the str to repeat
curStr = strStack.pop();
StringBuilder resStr = new StringBuilder();
int freq = freqStack.pop();
for (int i = 0; i < freq; i++) {
curStr.append(temp);
}
}
curIndex++;
}
return curStr.toString();
}
}
思路
抛出栈顶然后获取到数字repeat后加入栈
var decodeString = function(s) {
let stack=[];
for(let i=0;i<s.length;i++){
if(s[i]==']'){
let str=''
while(stack[stack.length-1]!='['){
let char=stack.pop()
str=char+str
}
stack.pop();
let num;
while(!isNaN(Number(stack[stack.length-1]))){
num=stack.pop()
stack.push(str.repeat(Number(num)))
}
}else{
stack.push(s[i])
}
}
return stack.join('')
};
复杂度 时间O(N),空间O(n)
【思路】用两个stack记录,一个记录string,一个记录数字。遍历string,碰到左括号[就往前看数字,算出结果,存入另一个stack中,碰到右括号就不停pop,直到发现左括号,这样就算出了substring,再pop出已经通过左括号算好的次数,形成有效的长度,在放回stack中,这样下一个括号迭代也可以把这个弄好的string放入计算。
但是这样其实弄复杂了。题解好像是在遍历string的时候,碰到数字就可以直接计算,每次往前*10就可以了,碰到左括号就直接加入int stack更方便了。少了一次while pop。[机智 【复杂度】O(n)
public String decodeString(String s) {
Stack<Character> num = new Stack<>();
Stack<Integer> each = new Stack<>();
Stack<String> decode = new Stack<>();
String ans = "";
for(int i = 0; i< s.length(); i++){
Character temp = s.charAt(i);
if(Character.isDigit(temp)){
num.push(temp);
}else if(temp == ']'){
String curr = decode.pop();
String local = "";
String total = "";
while(!curr.equals("[") ){
local = curr + local;
curr = decode.pop();
}
int times = each.pop();
for(int j = 0; j<times; j++){
total = total+local;
}
decode.push(total);
}else if(temp == '['){
decode.push(temp+"");
Character curr3 = num.pop();
int pos = 1;
int sum = curr3-'0';
while(curr3!='['&& !num.isEmpty()) {
pos = pos *10;
curr3 = num.pop();
int now = curr3-'0';
sum += pos * now;
}
each.add(sum);
}else{
decode.push(temp+"");
}
}
while(!decode.isEmpty()){
ans =decode.pop() + ans ;
}
return ans;
}
Explanation
Python
class Solution:
def decodeString(self, s: str) -> str:
stack = []
for ch in s:
if ch == "]":
curr = ""
while stack[-1] != "[":
curr = stack.pop() + curr
stack.pop()
num = ""
while stack and stack[-1].isdigit():
num = stack.pop() + num
currStr = curr * int(num)
stack.append(currStr)
else:
stack.append(ch)
return "".join(stack)
Complexity
O(N)
O(N)
默认写入栈,从内部往外面解开
1.遇到 ] 就回去先把所有字母弹出并且反转
2.在弹出数字。 根据数字复制字母在回写入栈,重复以上两步
Go Code:
func decodeString(s string) string {
var stack []byte
for i := 0; i < len(s); i++ {
c := s[i]
if c == 93 {
var d []byte
for stack[len(stack)-1] != 91 {
size := len(stack) - 1
d = append(d, stack[size])
stack = stack[:size]
}
d = reverse(d)
// 剔除[
stack = stack[:len(stack)-1]
digit := 1
num := 0
for len(stack) != 0 && stack[len(stack)-1] <= 57 {
size := len(stack) - 1
num += int(stack[size]-48) * digit
digit *= 10
stack = stack[:size]
}
for j := 1; j <= num; j++ {
stack = append(stack, d...)
}
} else {
stack = append(stack, c)
}
}
return string(stack)
}
func reverse(s []byte) []byte {
n := len(s)
for i := 0; i < n/2; i++ {
s[i], s[n-i-1] = s[n-i-1], s[i]
}
return s
}
复杂度分析
令 n 为数组长度。
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: 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"
Java Code:
public static String decodeString(String s) {
StringBuilder sb = new StringBuilder(s);
while (sb.indexOf("[") != -1) {
int leftIndex = sb.lastIndexOf("[");
int rightIndex = sb.indexOf("]", leftIndex);
String str = sb.substring(leftIndex + 1, rightIndex);
int i = leftIndex - 1, count = 0, base = 1;
while (i >= 0 && Character.isDigit(sb.charAt(i))) {
count += base * (sb.charAt(i) - '0');
base *= 10;
i--;
}
StringBuilder tmp = new StringBuilder();
for (int j = 0; j < count; j++) tmp.append(str);
sb = sb.replace(i + 1, rightIndex + 1, tmp.toString());
}
return sb.toString();
}
复杂度分析
令 n 为数组长度。
java
class Solution {
public String decodeString(String s) {
Stack<String> s2 = new Stack();
for(int i = 0;i < s.length();i++) {
if (Character.isDigit(s.charAt(i))) {
s2.push(String.valueOf(s.charAt(i)));
continue;
}
if ('['==(s.charAt(i)) || Character.isLowerCase(s.charAt(i))) {
s2.push(String.valueOf(s.charAt(i)));
continue;
}
if (']'== s.charAt(i)) {
List<String> c = new ArrayList<>();
while(!s2.peek().equals("[") ) {
c.add(String.valueOf(s2.pop()));
}
s2.pop();
Collections.reverse(c);
// 求[ 前面的数字
List<String> str = new ArrayList<>();
while(!s2.isEmpty() && Character.isDigit(s2.peek().charAt(0))) {
str.add(String.valueOf(s2.pop()));
}
Collections.reverse(str);
String tmp = getUsdString(str);
String appResult = getUsdString(c);
StringBuilder sb = new StringBuilder();
int count = Integer.parseInt(tmp);
while(count-- > 0) {
sb.append(appResult);
}
s2.push(sb.toString());
}
}
List<String> rest = new ArrayList<>();
while (!s2.isEmpty()) {
rest.add(s2.pop());
}
Collections.reverse(rest);
return getUsdString(rest);
}
private static String getUsdString(List<String> str) {
StringBuilder sb = new StringBuilder();
for (String s : str) {
sb.append(s);
}
return sb.toString();
}
}
从左至右遍历:
var decodeString = function(s) {
let i = 0, size = s.length;
var result = '';
var count = '';
var stack = [];
while (i < size) {
var c = s[i];
if (c === '[') {
stack.push([count, result]);
result = '';
count = '';
} else if (c === ']') {
var res = stack.pop();
result = res[1] + result.repeat(Number(res[0]));
} else if (/\d/.test(c)) {
// 数字
count += c;
} else {
// 字母
result += c;
}
i++;
}
return result;
};
时间:O(n) 空间:O(n)
模拟Stack
class Solution {
public:
string decodeString(string s) {
string res = "";
for (int i = 0; i < s.size(); i++) {
if (s[i] == ']') {
string str = "";
string cnt = "";
while (res.back() != '[') {
str = res.back() + str;
res.pop_back();
}
res.pop_back();
while (!res.empty() && isdigit(res.back())) {
cnt = res.back() + cnt;
res.pop_back();
}
int a = stoi(cnt);
while (a > 0) {
res.append(str);
a--;
}
} else {
res.push_back(s[i]);
}
}
return res;
}
};
思路: 用两个stack,一个记录出现的数字,一个记录字符串。 当遇到[的时候,就存储数字和字符串。 当遇到]的时候,就出栈,实现从内到外的这个打印效果。 其他时候就Concatenate char。
class Solution:
def decodeString(self, s: str) -> str:
numS, chaS = [], []
num, output = 0, ""
for c in s:
if c.isdigit():
num = num * 10 + int(c)
elif c == '[':
numS.append(num)
chaS.append(output)
num, output = 0, ""
elif c == ']':
output = chaS.pop() + output * numS.pop()
else:
output += c
return output
time complexity: O(N) space complexity: O(N)
思路: 建立一个栈,将每个字母遍历,如果没有遇到],就加入栈中,如果遇到[,则先弹出字母,再弹出数字,根据字母和数字经过处理后加入栈中,直到遍历完字母,栈中即为结果
class Solution {
public String decodeString(String s) {
Stack<Character> stack = new Stack<>();
for(char c: s.toCharArray()){
if(c != '['){
stack.push(c);
}
else{
StringBuffer sb = new StringBuffer();
while(!stack.isEmpty() && Character.isLetter(stack.peek())){
sb.insert(0, stack.pop());
}
String sub = sb.toString();
stack.pop();
sb = new StringBuffer();
while(!stack.isEmpty() && Character.isDigit(stack.peek())){
sb.insert(0, stack.pop());
}
int count = Integer.parseInt(sb.toString());
while(count > 0){
for(char ch: sub.toCharArray()){
stack.push(ch);
}
count--;
}
}
}
StringBuilder res = new StringBuilder();
while (!stack.isEmpty()) {
res.insert(0, stack.pop());
}
return res.toString();
}
}
时间复杂度空间复杂度均为O(N)
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"