leetcode-pp / 91alg-9-daily-check

5 stars 0 forks source link

【Day 4 】2022-11-04 - 394. 字符串解码 #11

Open azl397985856 opened 1 year ago

azl397985856 commented 1 year ago

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"

whoam-challenge commented 1 year ago

思路:

利用栈 后入先出的思想

代码:

class Solution:
    def decodeString(self, s: str) -> str:
        stack = []
        res = ""
        multi = 0
        for item in s:
            if item == '[':
                stack.append([res, multi])
                res = ""
                multi = 0
            elif item == ']':
                last_res, cur_multi = stack.pop()
                res = last_res + cur_multi * res
            elif '0' <=item <= '9':
                multi = multi * 10 + int(item)
            else:
                 res += item
        return res

复杂度分析

-时间复杂度 O(n) n是数组s的长度 -空间复杂度 O(n)

zjsuper commented 1 year ago

''' class Solution: def decodeString(self, s: str) -> str: ans = '' stack = [] cur_num = 0

    for i in range(len(s)):
        if s[i].isdigit():
            cur_num = cur_num*10 + int(s[i])
        elif s[i] == '[':
            stack.append((ans,cur_num))
            ans = ''
            cur_num = 0

        elif s[i] == ']':
            cur_str, n = stack.pop()
            ans = cur_str + ans *n
        else:
            ans += s[i]
    return ans

''' O(N)

steven72574 commented 1 year ago

思路:遍历字符串,当字符不是” ]“右括号时压入栈,遇到右括号时,栈弹出,在遇到 " [ "左括号前,把所有字符组成repeatString , 然后当还是数字时弹出,组成num,对repeatString 重复num次,再把新的字符串压入栈中。

class Solution {
    public String decodeString(String s) {
        int N = s.length();
        Stack<String> stack = new Stack<>();
        for(int i = 0 ; i < N ; i ++){
            String repeatStr = "";
            String num = "";
            String newString = "";
            String cur = s.substring(i , i + 1);
            if(!cur.equals("]") ){
                stack.push(s.substring(i , i+1));
            }else{
                while(!stack.isEmpty() && !stack.peek().equals("[")){
                    repeatStr = stack.pop() + repeatStr;
                }
                stack.pop();// pop :[
                while(!stack.isEmpty() && stack.peek().matches("[0-9]")){
                    num = stack.pop() + num;
                }
                for(int j = 0 ; j < Integer.valueOf(num) ; j++){
                    newString += repeatStr;
                }
                //把新字符串压回栈中
                for(int j = 0 ; j < newString.length() ; j++){
                    stack.push(newString.substring(j , j + 1));
                }
            }

        }
        String res = "";
        while(!stack.isEmpty()){
            res = stack.pop() + res;
        }
        return res;
    }
}

time O(n)
space O(n)

zhiyuanpeng commented 1 year ago
from collections import deque
class Solution:
    def decodeString(self, s: str) -> str:
        stack = deque()
        k = ""
        for i in range(len(s)-1, -1, -1):
            if s[i] in "0123456789":
                k += s[i]
            else:
                if k != "":
                    n = int(k[::-1])
                    temp = []
                    # pop until ] or end
                    while stack:
                        c = stack.popleft()
                        if c == "]":
                            break
                        else:
                            if c != "[":
                                temp.append(c)
                    # repeate k time
                    for _ in range(n):
                        # push back
                        for c in temp[::-1]:
                            stack.appendleft(c)
                    # clear k
                    k = ""
                stack.appendleft(s[i])
        if k != "":
            # repeate
            n = int(k[::-1])
            temp = []
            # pop until ] or end
            while stack:
                c = stack.popleft()
                if c == "]":
                    break
                else:
                    if c != "[":
                        temp.append(c) 
            # repeate k time
            for _ in range(n):
                # push back
                for c in temp[::-1]:
                    stack.appendleft(c)
        return "".join(stack)

time O(len(string)) space O(len(string)

FlipN9 commented 1 year ago
/**
    TC: O(n), SC: O(n)
*/

// Method 1: iterative
class Solution1 {
    public String decodeString(String s) {
        int multi = 0;
        StringBuilder sb = new StringBuilder();

        Deque<Integer> multi_stack = new ArrayDeque<>();
        Deque<String> chars_stack = new ArrayDeque<>();

        for (char c : s.toCharArray()) {
            if (c >= '0' && c <= '9') {                 // 1. 倍数
                multi = multi * 10 + (c - '0');
            } else if (c >= 'a' && c <= 'z') {          // 2. 字符
                sb.append(c);
            } else if (c == '[') {                      // 3. 入栈
                multi_stack.addLast(multi);             // 接下来[sb]要重复的次数
                chars_stack.addLast(sb.toString());     // 之前的sb
                multi = 0;                              // 重置临时变量
                sb = new StringBuilder();
            } else { // if (c == ']')                   // 4. 出栈
                StringBuilder tmp = new StringBuilder();
                int cur_multi = multi_stack.pollLast();
                for (int i = 0; i < cur_multi; i++)
                    tmp.append(sb);                     // sb * multi次
                sb = new StringBuilder(chars_stack.pollLast() + tmp);   // 把之前的和这一次的连起来
            }
        }
        return sb.toString();
    }
}

// Method 2: recursive
//      先解析数字 x, 解析到了左括号 [,递归向下解析后面的内容,遇到对应的右括号就返回 ]
//      [] 解析结束后, 再继续 解析] 右边的内容
class Solution {
    int i = 0;
    public String decodeString(String s) {
        int count = 0;
        StringBuilder sb = new StringBuilder();
        while (i < s.length()) {
            char c = s.charAt(i);
            i++;
            if (Character.isLetter(c)) {
                sb.append(c);
            } else if (Character.isDigit(c)) {
                count = count * 10 + (c - '0');
            } else if (c == ']') {      
                break;
            } else if (c == '[') {
                String repeat = decodeString(s);
                while (count > 0) {
                    sb.append(repeat);
                    count--;
                }
            }
        }
        return sb.toString();
    }
}
testplm commented 1 year ago
class Solution(object):
    def decodeString(self, s):
        # 两个栈,一个进数字,一个进字母,反括号出栈
        stack = [];curNum=0;curString=''
        for c in s:
            if c == '[':
                stack.append(curString)
                stack.append(curNum)
                curString = ''
                curNum = 0
            elif c == ']':
                num = stack.pop()
                prevString = stack.pop()
                curString = prevString + num*curString
            elif c.isdigit():
                curNum = curNum*10 + int(c)
            else:
                curString += c
        return curString
Whisht commented 1 year ago

思路

将每个字符入栈 ,当遇到 ']' 时出栈,直至遇到 '[''[' 前的所有数字出栈,即为 k,将出栈得到的括号内所有字符重复 k 次,入栈。

代码

class Solution:
    def decodeString(self, s: str) -> str:
        stack = []
        res = ""
        for i in s:
            if i == "]":
                tmp = stack.pop()
                ch = ""
                while tmp != "[": # "[" 之后的字符为当前要处理的子串
                    ch = tmp + ch
                    tmp = stack.pop()
                time = 0
                c = 0 # 进位,因为数字取值为 [1, 300],需要考虑 10 以上的重复情况
                while stack and stack[-1].isdigit(): # "[" 之前的数字为当前子串要重复的次数
                    t1 = stack.pop()
                    time += int(t1) * 10 ** c
                    c += 1
                ch = ch * time
                stack.append(ch) # 处理完的子串入栈
            else:
                stack. append (i)
        if stack:
            res = "".join(i for i in stack)
        return res

复杂度

ShuqianYang commented 1 year ago

class Solution {
    int ptr;

    public String decodeString(String s) {
        LinkedList<String> stk = new LinkedList<String>();
        ptr = 0;

        while (ptr < s.length()) {
            char cur = s.charAt(ptr);
            if (Character.isDigit(cur)) {
                // 获取一个数字并进栈
                String digits = getDigits(s);
                stk.addLast(digits);
            } else if (Character.isLetter(cur) || cur == '[') {
                // 获取一个字母并进栈
                stk.addLast(String.valueOf(s.charAt(ptr++))); 
            } else {
                ++ptr;
                LinkedList<String> sub = new LinkedList<String>();
                while (!"[".equals(stk.peekLast())) {
                    sub.addLast(stk.removeLast());
                }
                Collections.reverse(sub);
                // 左括号出栈
                stk.removeLast();
                // 此时栈顶为当前 sub 对应的字符串应该出现的次数
                int repTime = Integer.parseInt(stk.removeLast());
                StringBuffer t = new StringBuffer();
                String o = getString(sub);
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 将构造好的字符串入栈
                stk.addLast(t.toString());
            }
        }

        return getString(stk);
    }

    public String getDigits(String s) {
        StringBuffer ret = new StringBuffer();
        while (Character.isDigit(s.charAt(ptr))) {
            ret.append(s.charAt(ptr++));
        }
        return ret.toString();
    }

    public String getString(LinkedList<String> v) {
        StringBuffer ret = new StringBuffer();
        for (String s : v) {
            ret.append(s);
        }
        return ret.toString();
    }
}
Yongxi-Zhou commented 1 year ago

思路

如果不是']',就把当前字符放入 stack 中,否则就把从 stack pop 出 string 和 repeat time,最后再把结果放在栈里面

代码

    class Solution:
        def decodeString(self, s: str) -> str:
            stack = []
            for char in s:
                if char != "]":
                    stack.append(char)
                else:
                    temp = ""
                    count = ""
                    while len(stack) != 0 and stack[-1] != "[":
                        temp = stack.pop() + temp
                    stack.pop()
                    while len(stack) != 0 and stack[-1].isdigit():
                        count = stack.pop() + count
                    stack.append(temp * int(count))
            return  "".join(stack)

复杂度

time O(N)
space O(N)

buer1121 commented 1 year ago
    # ###思想:想法是栈,如果每次一个新的[,就入栈之前的字符串,当遇到],便进行计算

    ###代码:
    stack=[]
    res=""
    multi=0
    for c in s:
        if c=="[":
            stack.append([multi,res])
            multi,res=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
gsw9818 commented 1 year ago

思路

循环字符串s 非 "]" 默认全部入栈 遇到"]"时 维护strs和repeat两个空字符串 先while循环获取所有字符串,条件为stack[-1] != 'a strs = stack.pop() + strs 执行一次stack.pop() 删掉“[” 再次while循环,条件为栈存在且栈顶为数字类型的字符串(“3[a]”场景,必须判断栈不为空) repeat = stack.pop() + repeat 现在栈中压入int(repeat) * strs即可

代码

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)

复杂度

双O(N)

pyxyzc commented 1 year ago

字符串解码

输入:s = "3[a]2[bc]"
输出:"aaabcbc"

括号内嵌套括号,需要从内向外生成与拼接字符串,和栈先入后出的特性对应。

class Solution
{
public:
    string decodeString(string s)
    {
        vector<string> strstk;
        vector<int> numstk;

        int num = 0;
        string str = "";
        for (char c : s)
        {
            if (c >= '0' && c <= '9')
            {
                num *= 10;
                num += (c - '0');
            }
            else if (c == '[')
            {
                numstk.push_back(num);
                strstk.push_back(str);
                num = 0;
                str = "";
            }
            else if (c == ']')
            {
                int numtmp = numstk.back();
                string strtmp = strstk.back();
                numstk.pop_back();
                strstk.pop_back();
                for (int i = 0; i < numtmp; i++)
                {
                    strtmp = strtmp + str;
                }
                str = strtmp;
            }
            else
            {
                str += c;
            }
        }
        return str;
    }
};
954545647 commented 1 year ago

思路

使用栈维护当前【】进出

代码

/**
 * @param {string} s
 * @return {string}
 */
 var decodeString = function(s) {
  let res = ""
  let stack = [];
  let multi = 0;
  for(let  i = 0; i < s.length;i++){
    const item = s[i];
    const isNum = !isNaN(Number(item));
    const isLBrackets = item === "["
    const isRBrackets = item === "]"
    if(isNum){
      multi = Number(`${multi}${item}`);
    }else if(isLBrackets){
      stack.push([multi,res])
      res = "";
      multi = 0
    }else if(isRBrackets){
      const stackItem = stack.pop();
      res = stackItem[1] + res.repeat(stackItem[0])
    }else{
      res += item
    }
  }
  return res
};

复杂度分析

Alyenor commented 1 year ago
function decodeString(s: string): string {
  let res = ''
  let count = 0
  let stack: [string, number][] = []

  const sArr = s.split('')
  for (const c of sArr) {
    if (c === '[') {
      stack.push([res, count])
      count = 0
      res = ''
    } else if (c === ']') {
      const ans = stack.pop()!
      const chars = ans[0]
      const times = ans[1]
      let temp = ''
      for (let i = 0; i < times; i++) {
        temp += res
      }
      res = chars + temp
    } else if (c <= '9' && c >= '0') {
      count = count * 10 + parseInt(c)
    } else {
      res += c
    }
  }
  return res
};
heng518 commented 1 year ago

class Solution { public: string decodeString(string s) { stack string_S; stack int_S;

    int index = 0;
    string curRes = "";
    while(index < s.size())
    {
        if(s[index] >= '0' && s[index] <= '9')
        {
            int count = 0;
            while(s[index] >= '0' && s[index] <= '9')   
            {
                count = 10 * count + (s[index] - '0');
                index++;
            }
            int_S.push(count);
        }

        else if(s[index] == '[')
        {
            string_S.push(curRes);
            curRes = "";
            index++;
        }

        else if(s[index] == ']')
        {
            string tempStr = string_S.top();
            int repeatCount = int_S.top();

            string_S.pop();
            int_S.pop();

            while(repeatCount > 0)
            {
                tempStr.append(curRes);
                repeatCount--;
            }

            curRes = tempStr;
            index++;
        }

        else
        {
            curRes += s[index];
            index++;
        }
    }

    return curRes;
}

};

bookyue commented 1 year ago

code

class Solution {
    public String decodeString(String s) {
        Deque<Character> deque = new ArrayDeque<>();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c != ']') deque.addFirst(c);
            else {
                StringBuilder sb = new StringBuilder();
                while (!deque.isEmpty() && Character.isLetter(deque.getFirst()))
                    sb.insert(0, deque.removeFirst());

                String sub = sb.toString();
                deque.removeFirst(); // remove '['

               sb = new StringBuilder();
               while (!deque.isEmpty() && Character.isDigit(deque.getFirst()))
                   sb.insert(0, deque.removeFirst());

               int count = Integer.parseInt(sb.toString());

                for (char ch : sub.repeat(count).toCharArray())
                    deque.addFirst(ch);
            }
        }

        StringBuilder sb = new StringBuilder();
        while (!deque.isEmpty())
            sb.append(deque.removeLast());

        return sb.toString();
    }
}
Jetery commented 1 year ago

394. 字符串解码

思路 1: 双栈

代码 (cpp)

class Solution {
public:
    string decodeString(string s) {
        stack<int> num;
        int n = 0;
        stack<string> str;
        string ans = "";
        for (char c : s) {
            if (c >= '0' && c <= '9') {
                n = n * 10 + c - '0';
            } else if (c == '[') {
                num.push(n);
                n = 0;
                str.push(ans);
                ans = "";
            } else if (c == ']') {
                int t = num.top();
                num.pop();
                for (int i = 0; i < t; i++) {
                    str.top() += ans;
                }
                ans = str.top();
                str.pop();
            } else {
                ans += c;
            }
        }
        return ans;
    }

};

复杂度分析


思路 2: 栈 + 递归

代码 (cpp)

class Solution {
public:
    string helper(stack<char> &stack) {
        int n = 0;
        string ret = "";
        while (!stack.empty()) {
            char c = stack.top();
            stack.pop();
            if (c >= '0' && c <= '9') {
                n = n * 10 + c - '0';
            } else if (c == '[') {
                string sub = helper(stack);
                for (int i = 0; i < n; i++) {
                    ret += sub;
                }
                n = 0;
            } else if (c == ']'){
                break;
            } else {
                ret += c;
            }
        }
        return ret;
    }

    string decodeString(string s) {
        stack<char> stack;
        for (int i = s.size() - 1; i >= 0; i--)
            stack.push(s[i]);
        string ret = helper(stack);
        return ret;
    }
};

复杂度分析

jmaStella commented 1 year ago

思路

  1. 用了一种非常离谱非常麻烦的方法,一个栈记录数字,一个栈记录letter,遇到 "]"时pop出repeat string,再pop一个数字做repeat, 有很多edge case,比如如何check是数字,check两个栈的size
  2. java 好像对双引号or单引号很敏感,单引号的时候做character比较会有error 代码

    class Solution {
    public String decodeString(String s) {
        String str = "";
        Stack<String> letter = new Stack<>();
        Stack<Integer> nums = new Stack<>();
        String num = "";
        for(int i=0; i<s.length(); i++){
    
            if(Character.isDigit(s.charAt(i))){
                num= num + s.charAt(i);
                System.out.println("[get num " + num);
            }else if(s.charAt(i) == '['){
                if(num.length()>0){
                    nums.push(Integer.parseInt(num));
                    System.out.println("[[nums push "+ Integer.parseInt(num));
                    num = "";
                }
    
                letter.push(" ");
            }else if(s.charAt(i) == ']'){
                String sub = "";
                while(letter.peek() != " "){
                    sub = letter.pop() + sub;
                }
                letter.pop();
                if(nums.size() >0){
                    letter.push(sub.repeat(nums.pop()));
                    System.out.println("repeat "+ sub);
                }else{
                    letter.push(sub);
                    System.out.println("purer push "+ sub);
                }
    
            }else{
                letter.push(String.valueOf(s.charAt(i)));
                System.out.println("final else"+ s.charAt(i));
            }
        }
        while(!letter.isEmpty()){
            str=  letter.pop() + str;
        }
        return str;
    }
    }

    时间复杂度:O(N) 空间复杂度:O(N)

Abby-xu commented 1 year ago

思路

用stack存储,四个cases

代码

class Solution:
    def decodeString(self, s: str) -> str:
        stack = []
        current_string = ""
        k = 0

        for char in s:
            if char == "[":
                # Just finished parsing this k, save current string and k for when we pop
                stack.append((current_string, k))
                # Reset current_string and k for this new frame
                current_string = ""
                k = 0
            elif char == "]":
                # We have completed this frame, get the last current_string and k from when the frame 
                # opened, which is the k we need to duplicate the current current_string by
                last_string, last_k = stack.pop(-1)
                current_string = last_string + last_k * current_string
            elif char.isdigit():
                k = k * 10 + int(char)
            else:
                current_string += char

        return current_string
JancerWu commented 1 year ago

思路

当遇到左括号时,需要用栈保存前面的解码结果,即用到一个字符串栈,同时需要保存前面的次数,即用到一个数量栈;遇到右括号时,数量栈顶为当前字符串的重复次数。

代码

class Solution {
    public String decodeString(String s) {
        Deque<String> cStack = new ArrayDeque<>();
        Deque<Integer> numStack = new ArrayDeque<>();
        int num = 0;
        String ans = "";
        for (char c : s.toCharArray()) {
            if (Character.isDigit(c)) {
                num = num * 10 + c - '0';
            } 
            else if (Character.isLetter(c)) {
                ans += c;
            }
            else if (c == '[') {
                numStack.push(num);
                num = 0;
                cStack.push(ans);
                ans = "";
            }
            else if (c == ']') {
                int cnt = numStack.pop();
                String str = cStack.pop();
                for (int i = 1; i <= cnt; i++) {
                    str += ans;
                }
                ans = str;
            }
        }
        return ans;
    }
}

复杂度

zywang0 commented 1 year ago

Code

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();
    }
}

Time Complexity

Time: O(n) Space: O(n)

MaylingLin commented 1 year ago

思路


双栈,一个栈存放数字,一个栈存放字母

代码

class Solution:
    def decodeString(self, s: str) -> str:
        stack = []
        for c in s:
            if c == "]":
                tmpstr = ""
                numstr = ""
                while stack and stack[-1] != "[":
                    char = stack.pop()
                    tmpstr = char + tmpstr
                stack.pop()
                while stack and stack[-1].isdigit():
                    num = stack.pop()
                    numstr = num + numstr
                stack.append(int(numstr) * tmpstr)
            else:
                stack.append(c)
        return "".join(stack)

复杂度

yin02 commented 1 year ago

思路

如果当前的字符为数位,解析出一个数字(连续的多个数位)并进栈 如果当前的字符为字母或者左括号,直接进栈 如果当前的字符为右括号,开始出栈,一直到左括号出栈,出栈序列反转后拼接成一个字符串,此时取出栈顶的数字(这个次数和字符串构造出新的字符串并进栈

代码

class Solution:
    def decodeString(self, s: str) -> str:
        def dfs(s, i):
            res, multi = "", 0
            while i < len(s):
                if '0' <= s[i] <= '9':
                    multi = multi * 10 + int(s[i])
                elif s[i] == '[':
                    i, tmp = dfs(s, i + 1)
                    res += multi * tmp
                    multi = 0
                elif s[i] == ']':
                    return i, res
                else:
                    res += s[i]
                i += 1
            return res
        return dfs(s,0)

复杂度分析 时间复杂度 O(N),递归会更新索引,因此实际上还是一次遍历 s; 空间复杂度 O(N),极端情况下递归深度将会达到线性级别。

Serena9 commented 1 year ago

思路

使用栈,遍历字符串,将字符数字和‘【’入栈,直到碰到‘】’,开始出栈,将‘【’之前的字符出栈存在restr里面,然后将‘【’之后的数字出栈存在num中,然后将num倍的restr入栈,直到遍历结束

代码

class Solution:
    def decodeString(self, s: str) -> str:
        stk = []
        for x in s:
            if x==']':
                restr = ''
                num = ''
                while stk and stk[-1]!='[':
                    restr = stk.pop()+restr
                stk.pop()
                while stk and stk[-1].isnumeric():
                    num = stk.pop()+num
                stk.extend(restr*int(num))
            else:
                stk.append(x)
        return ''.join(stk)

复杂度分析

snmyj commented 1 year ago
class Solution:

    def decodeString(self, s: str) -> str:

        result = ''
        string_stack = []
        data = 0
        for i in s:
            if(i.isdigit()):
                data = data*10 + int(i)

            elif(i == '['):
                string_stack.append([data, result])
                result = ''
                data = 0

            elif(i.isalpha()):
                result += i

            elif(i == ']'):
                result = string_stack[-1][1] + string_stack[-1][0] * result
                string_stack.pop()
        return result
A-pricity commented 1 year ago
/**
    利用栈的思想解题
      设置两个变量:1.res 最终结果字符串 2.num 用来计数当前字符需要重复多少次 
      构造两个栈:1.字符栈 strStack,表示需要重复的字符 2.数字栈,需要重复的次数 
      如果当前 str === 数字,推入数字栈 
      如果当前 str === [,strStack、numStack 入栈,num,res 清 0 
      如果当前 str === ],strStack、numStack 出栈,形成一次字符串 
      其他情况 把字符加到 res 中
 */
/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function (s) {
    let numStack = [],strStack = [],res = '',num = 0;

    for (let str of s) {
        if (!isNaN(str)) {
            num = num * 10 + parseInt(str);
        } else if (str === '[') {
            strStack.push(res);
            numStack.push(num);
            res = '';
            num = 0;
        } else if (str === ']') {
            res = strStack.pop() + res.repeat(numStack.pop());
        } else {
            res += str;
        }
    }
    return res;
};
nineis7 commented 1 year ago

394

暂时没做出来,C++的string用得不是很习惯

代码

class Solution {
public:
    string decodeString(string s) {
        string res_str;
        string tmp_str;
        stack <int> stk;
        int i(0);
        int n(0);
        //int k(0), count(0);
        while(i < s.length()){
            if((s[i]-'0' >= 0) && (s[i]-'0' <= 9)) stk.push(s[i++]);
            else if(s[i] == '[') {
                stk.push(s[i++]);
                n++;
            }
            else if(s[i] == ']') {
                string tmp;
                while(stk.top() != '['){
                    //tmp 
                    string tmp3;
                    tmp3 += stk.top();
                    tmp.insert(0, tmp3);
                    stk.pop();
                }
                tmp_str.insert(0, tmp);
                //cout << tmp_str << endl;
                stk.pop();
                n--;
                int k(0), count(0);
                while(!stk.empty() && (stk.top()-'0' >= 0) && (stk.top()-'0' <= 9)){
                    int tmpn = stk.top() -'0';
                    k += tmpn*pow(10,count++);
                    stk.pop();
                }
                string tmp2(tmp_str);
                k--;
                while(k){
                    tmp_str += tmp2;
                    k--;
                }
                if(!n) {
                    res_str.append(tmp_str);
                    tmp_str.clear();
                }

                ++i;
            }
            else {
                if (stk.empty()) res_str += s[i++];
                else stk.push(s[i++]);
            }

        }

        return res_str;
    }
};
1541732340 commented 1 year ago

算法流程: 1、构建辅助栈 stack, 遍历字符串 s 中每个字符 c; 1.1当 c 为数字时,将数字字符转化为数字 multi,用于后续倍数计算; 1.2当 c 为字母时,在 res 尾部添加 c; 1.3当 c 为 [ 时,将当前 multi 和 res 入栈,并分别置空置 1.3.1记录此 [ 前的临时结果 res 至栈,用于发现对应 ] 后的拼接操作; 1.3.2记录此 [ 前的倍数 multi 至栈,用于发现对应 ] 后,获取 multi × [...] 字符串。 1.3.3进入到新 [ 后,res 和 multi 重新记录。 1.4当 c 为 ] 时,stack 出栈,拼接字符串 res = last_res + cur_multi * res,其中: 1.4.1last_res是上个 [ 到当前 [ 的字符串,例如 "3[a2[c]]" 中的 a; 1.4.2cur_multi是当前 [ 到 ] 内字符串的重复倍数,例如 "3[a2[c]]" 中的 2。 2、返回字符串 res。

代码:java

class Solution { public String decodeString(String s) { StringBuilder res = new StringBuilder(); int multi = 0; LinkedList stack_multi = new LinkedList<>(); LinkedList 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) 空间复杂度 O(N)

AstrKing commented 1 year ago

思路

利用栈的思想,数字、字母和中括号分开,数字、字母和左括号直接进,遇到右括号的时候出栈,然后一直到遇到左括号停止,反转一下就是我们的字母队列,再去栈里面找数字就是重复的次数,然后根据新的字符串再进栈,如此循环往复即可

代码

class Solution {
    int ptr;

    public String decodeString(String s) {
        LinkedList<String> stk = new LinkedList<String>();
        ptr = 0;

        while (ptr < s.length()) {
            char cur = s.charAt(ptr);
            if (Character.isDigit(cur)) {
                // 获取一个数字并进栈
                String digits = getDigits(s);
                stk.addLast(digits);
            } else if (Character.isLetter(cur) || cur == '[') {
                // 获取一个字母并进栈
                stk.addLast(String.valueOf(s.charAt(ptr++))); 
            } else {
                ++ptr;
                LinkedList<String> sub = new LinkedList<String>();
                while (!"[".equals(stk.peekLast())) {
                    sub.addLast(stk.removeLast());
                }
                Collections.reverse(sub);
                // 左括号出栈
                stk.removeLast();
                // 此时栈顶为当前 sub 对应的字符串应该出现的次数
                int repTime = Integer.parseInt(stk.removeLast());
                StringBuffer t = new StringBuffer();
                String o = getString(sub);
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 将构造好的字符串入栈
                stk.addLast(t.toString());
            }
        }

        return getString(stk);
    }

    public String getDigits(String s) {
        StringBuffer ret = new StringBuffer();
        while (Character.isDigit(s.charAt(ptr))) {
            ret.append(s.charAt(ptr++));
        }
        return ret.toString();
    }

    public String getString(LinkedList<String> v) {
        StringBuffer ret = new StringBuffer();
        for (String s : v) {
            ret.append(s);
        }
        return ret.toString();
    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(n)

yuexi001 commented 1 year ago

思路

  1. 使用栈st存储pair( ]前字母,]前数字 )
  2. 遍历s,如果是字母,存入nowStr;如果是数字,存入nowNum;如果是'[',将(nowStr, nowNum)入栈,并清空nowStr和nowNum;如果是']',说明已经找到一个完整的子串可以用来表示总长度,此时nowStr存储的是[]里字符串,此时栈顶元素出栈,atoi(st.back().second.c_str())是nowStr出现次数,st.back().first是这个出现多次的字符串前的字符串,将展开后的子串存入nowStr即为当前已经展开一次的串。
  3. 遍历结束,返回结果nowStr

代码

C++ Code:

class Solution {
public:
    string decodeString(string s) {
        vector<pair<string, string>>st;
        string nowStr, nowNum;
        for(int i = 0; i < s.size(); i++){
            if(s[i] >= 'a' && s[i] <= 'z'){
                nowStr += s[i];
            }else if(s[i] >= '0' && s[i] <= '9'){
                nowNum += s[i];
            }else if(s[i] == '['){
                st.push_back(make_pair(nowStr, nowNum));
                nowStr.clear();
                nowNum.clear();
            }else{
                string tmp;
                for(int j = 0; j < atoi(st.back().second.c_str()); j++)
                    tmp += nowStr;
                nowStr =  st.back().first + tmp;
                st.pop_back();     
            }
        }
        return nowStr;
    }
};

复杂度分析

令 n 为数组长度。

xuanaxuan commented 1 year ago

思路

循环 + 栈

/*

// @lc code=start /**

复杂度分析

时间复杂度:$O(S)$,S 是解析后字符串的长度。 空间复杂度:$O(S)$,S 是解析后字符串的长度。

klspta commented 1 year ago

思路

递归,返回内部字符串 和 计算到了哪个位置;每次遇到[ 就进入下层,遇到 ] 就发返回;


class Solution {
    public String decodeString(String s) {
        char[] str = s.toCharArray();
        return process(str, 0).res;
    }

    private Info process(char[] str, int index){
        StringBuilder sb = new StringBuilder();
        int count = 0;
        while(index < str.length){
            char c = str[index];
            if(c >= '0' && c <= '9'){
                count = count * 10 + (c - '0');
            }else if(c == '['){
                Info info = process(str, index + 1);
                while(count > 0){
                    sb.append(info.res);
                    count--;
                }
                index = info.index;
            }else if(c == ']'){
                return new Info(sb.toString(), index);
            }else {
                sb.append(c);
            }
            index++;
        }
        return new Info(sb.toString(), index);
    }
}

class Info{
    String res;
    Integer index;

    Info(String res, Integer index){
        this.res = res;
        this.index = index;
    }
}

时空分析

O(n), O(1)

hanschurer commented 1 year ago

class Solution: def decodeString(self, s: str) -> str: stk = [] for x in s: if x==']': restr = '' num = '' while stk and stk[-1]!='[': restr = stk.pop()+restr stk.pop() while stk and stk[-1].isnumeric(): num = stk.pop()+num stk.extend(restr*int(num)) else: stk.append(x) return ''.join(stk)

AtaraxyAdong commented 1 year ago

思路

最后写的脑袋晕晕沉沉,总算是ac了

维护两个stack,一个是数字栈,一个是字符串栈,遍历给定的字符串char c = s.charAt(i)

直到遍历完成

代码

class Solution {
    public String decodeString(String s) {

        Stack<Integer> numStack = new Stack<>();
        Stack<StringBuffer> stringStack = new Stack<>();

        StringBuffer result = new StringBuffer();
        int multi = 0;

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (Character.isDigit(c)) {
                multi = 10 * multi + c - '0';
            } else if (c == '[') {
                stringStack.push(result);
                numStack.add(multi);
                result = new StringBuffer();
                multi = 0;
            } else if (Character.isAlphabetic(c)) {
                //记录当前小段的 string
                result.append(c);
            } else if (c == ']') {
                // decode
                StringBuffer temp = stringStack.pop();
                multi = numStack.pop();
                for (int j = 0; j < multi; j++) temp.append(result);
                multi = 0;
                result = temp;
            }
        }
        return result.toString();
    }
}

复杂度分析

zhuzhu096 commented 1 year ago

class Solution { public: string src; size_t ptr;

int getDigits() {
    int ret = 0;
    while (ptr < src.size() && isdigit(src[ptr])) {
        ret = ret * 10 + src[ptr++] - '0';
    }
    return ret;
}

string getString() {
    if (ptr == src.size() || src[ptr] == ']') {
        // String -> EPS
        return "";
    }

    char cur = src[ptr]; int repTime = 1;
    string ret;

    if (isdigit(cur)) {
        // String -> Digits [ String ] String
        // 解析 Digits
        repTime = getDigits(); 
        // 过滤左括号
        ++ptr;
        // 解析 String
        string str = getString(); 
        // 过滤右括号
        ++ptr;
        // 构造字符串
        while (repTime--) ret += str; 
    } else if (isalpha(cur)) {
        // String -> Char String
        // 解析 Char
        ret = string(1, src[ptr++]);
    }

    return ret + getString();
}

string decodeString(string s) {
    src = s;
    ptr = 0;
    return getString();
}

};

hxj2001 commented 1 year ago

思路

利用一个数字栈与一个符号栈来处理,首先遍历整个字符串,如果当前的字符为数字,字母或者左括号,直接进栈,如果当前的字符为右括号,开始出栈,一直到左括号出栈,出栈序列反转后拼接成一个字符串,取出栈顶的数字,根据字符串构造出新的字符串并进栈

代码

class Solution {  
public:  
   string decodeString(string s) {     
       stack<int> st_num;   //数字栈  
       string symbol;    
       int num=0;   
       for(int i=0;i<s.size();i++)
       {
           if(s[i]>='0'&&s[i]<='9'){   
               num=s[i]-'0'+num*10;  
           }else if(s[i]=='['){      
               st_num.push(num);  
              num=0;  
               symbol+=s[i];  
           }else if(s[i]==']'){     
              int j=symbol.size()-1;  
               string tmp_string;  
               while(symbol[j]!='[')  
               {  
                   tmp_string+=symbol[j];  
                  symbol.pop_back();  
                   j--;  
               }  
              symbol.pop_back();  
               int tmp_num=st_num.top();  
               st_num.pop();  
               reverse(tmp_string.begin(),tmp_string.end());  
               for(int k=0;k<tmp_num;k++)  
               {  
                   symbol+=tmp_string;  
               }  
           }else{   
               symbol+=s[i];  
           }  
       }  
       return symbol;  
   }  
};   
maoting commented 1 year ago

思路:

遍历数组,

  1. 如果是'[',直接入栈
  2. 如果是'数字',将连续数字字符识别出来,统一放入栈中
  3. 如果是']',进行处理
    • ① 连续获取字符串,直到遇到”[“
    • ② 取出数字
    • ③ 计算出字符串后再入栈
  4. 如果是'普通字符',正常入栈

代码

var decodeString = function(s) {
    let stack = [];
    let len = s.length;
    let i = 0;
    while(i < len) {
        let char = s[i];
        if (char === '[') {
            stack.push('[');
            i++;
        }
        else if (/[0-9]/.test(+s[i])) {
            let strNum = s[i];
            i++;
            while(/[0-9]/.test(+s[i])) {
                strNum += s[i];
                i++;
            }
            stack.push(strNum)
        }
        else if (char === ']') {
            let str = stack.pop();
            let cur = stack.pop();
            while(true) {
                if (cur === '[') break;
                str = cur + str;
                cur = stack.pop();
            }

            const num = +stack.pop();
            const strList = Array(num).fill().map(() => str).join('');
            stack.push(strList);
            i++;
        }
        else {
            stack.push(s[i]);
            i++;
        }

    }
    return stack.join('');
};

复杂度分析

wabw1 commented 1 year ago

解题思路

栈的使用

  1. 判断类型: 数字、字母、[、]
    1. 数字 更新m 直接拼接
    2. 字母,更新res, 直接拼接
    3. [: 入栈 stack.push([res, +m])
    4. ]: 出栈 res = pop出来的res + 当前res.repeat(pop出来的multi)

JS的一些语法复习:

  1. 重复3次的str: a. str.repeat(3) ES6的语法 b. new Array(3).fill(str).join("") c. new Array(4).join(str)
  2. ASCII码: 0-9 : 48-57 ; 字母a-z: 97-122

代码

/**
 * @param {string} s
 * @return {string}
 */

var decodeString = function(s) {
  let m = "";
  let stack = [];
  let res = "";
  for(let i=0;i<s.length;i++){
    let asc = s[i].charCodeAt();
    // 数字 更新m 直接拼接
    if (asc>=48 && asc<=57){
      m += s[i];  
    } else if(asc>=97 && asc<=122){
      // 字母 更新res
      res += s[i];
    } else if(s[i]==='['){
      // 入栈[res,m] 置空这两个
      stack.push([res,+m]);
      res = '';
      m = '';
    } else if(s[i]===']'){
      // 出栈
      let [beforeRes,multi] = stack.pop();
      res = beforeRes+ res.repeat(multi);
    }
  }
  return res;
};

复杂度

空间:O(N) 时间:O(N)

Weisday commented 1 year ago
class Solution {
    public String decodeString(String s) {
        return dfs(s, 0)[0];
    }
    private String[] dfs(String s, int i) {
        StringBuilder res = new StringBuilder();
        int multi = 0;
        while(i < s.length()) {
            if(s.charAt(i) >= '0' && s.charAt(i) <= '9') 
                multi = multi * 10 + Integer.parseInt(String.valueOf(s.charAt(i))); 
            else if(s.charAt(i) == '[') {
                String[] tmp = dfs(s, i + 1);
                i = Integer.parseInt(tmp[0]);
                while(multi > 0) {
                    res.append(tmp[1]);
                    multi--;
                }
            }
            else if(s.charAt(i) == ']') 
                return new String[] { String.valueOf(i), res.toString() };
            else 
                res.append(String.valueOf(s.charAt(i)));
            i++;
        }
        return new String[] { res.toString() };
    } 
}
xiaomingshixiaotang commented 1 year ago

思路

  1. 采用分配律的思想
  2. 用一个栈保存数字,后出现的先使用;用一个栈保存高层级(外层)的字符串
  3. 当出现左括号时,说明应该保存这一层级的数字,以及上一层级的字符串(进行push操作);当出现右括号时,说明应该获取当前层级的数字,用来作为循环条件(即进行乘法分配),获取上一层级的字符串与当前层级的字符串进行循环拼接,得到上一层级的字符串,(使用结束进行pop操作)

代码

class Solution {
public:
    string decodeString(string s) {
        string res = "";
        int num = 0;
        stack<int> nums;
        stack<string> lesserStrs;

        int len = s.size();
        for(int i = 0;i < len;i++)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                num = num * 10 + (s[i] - '0');
            }
            else if(s[i] >= 'a' && s[i] <= 'z')
            {
                res = res + s[i];
            }
            else if(s[i] == '[')
            {
                lesserStrs.push(res);
                res = "";
                nums.push(num);
                num = 0;
            }
            else if(s[i] == ']')
            {
                int n = nums.top();
                nums.pop();
                for(int i = 0;i < n;i++)
                {
                    lesserStrs.top() = lesserStrs.top() + res;   
                }
                res = lesserStrs.top();
                lesserStrs.pop();
            }
        }

        return res;
    }
};
};

复杂度分析

sclihuiming commented 1 year ago

思路

模拟栈,并且插入一个 # 号键作为标识符

代码

func decodeString1(s string) string {
    ans := []rune{}

    i := true
    for _, elem := range s {
        if elem >= '0' && elem <= '9' && i {
            ans = append(ans, '#', elem)
            i = false
        } else if elem == '[' {
            i = true
            ans = append(ans, elem)
        } else if elem == ']' {
            i = true
            tmpStr := ""
            amountStr := ""
            flag := false
            for len(ans) > 0 {
                popElem := ans[len(ans)-1]
                ans = ans[:len(ans)-1]
                if popElem == '#' {
                    break
                } else if popElem == '[' {
                    flag = true
                } else if flag {
                    amountStr = string(popElem) + amountStr
                } else {
                    tmpStr = string(popElem) + tmpStr
                }
            }
            amount := 1
            if amountStr != "" {
                amount, _ = strconv.Atoi(amountStr)
            }
            str := ""
            for index := 0; index < amount; index++ {
                str += tmpStr
            }
            ans = append(ans, []rune(str)...)

        } else {
            ans = append(ans, elem)
        }
    }
    return string(ans)
}
wtdcai commented 1 year ago

代码

class Solution:
    def decodeString(self, s: str) -> str:
        stack, cstr, num = [], "", 0
        for i in s:
            if "0" <= i <= "9":
                num = num*10 + int(i)
            elif i == "[":
                stack.append((cstr,num))
                cstr, num = "", 0
            elif i == ']':
                _cstr,_num = stack.pop()
                cstr = _cstr + cstr * _num
            else:
                cstr += i 
        return cstr

复杂度分析

O(n)
O(n)

ronething commented 1 year ago

思路

用栈实现

代码

package issue9

import (
    "strconv"
    "strings"
)

func decodeString(s string) string {
    ptr := 0
    var stk []string

    var getDigits func() string
    getDigits = func() string {
        // 获取数字
        ret := ""
        for ; s[ptr] >= '0' && s[ptr] <= '9' && ptr < len(s); ptr++ {
            ret += string(s[ptr])
        }
        return ret
    }

    var getString func(v []string) string
    getString = func(v []string) string {
        return strings.Join(v, "")
    }

    for ptr < len(s) {
        cur := s[ptr]
        if cur >= '0' && cur <= '9' { // 获取数字
            digits := getDigits()
            stk = append(stk, digits)
        } else if (cur >= 'a' && cur <= 'z' || cur >= 'A' && cur <= 'Z') || cur == '[' {
            stk = append(stk, string(cur))
            ptr++
        } else { // 右花括号
            var sub []string
            for stk[len(stk)-1] != "[" {
                sub = append(sub, stk[len(stk)-1])
                stk = stk[:len(stk)-1] // 出栈
            }
            stk = stk[:len(stk)-1] // 将 "[" pop 出栈
            // 逆序
            for i := 0; i < len(sub)/2; i++ {
                sub[i], sub[len(sub)-i-1] = sub[len(sub)-i-1], sub[i]
            }
            repTime, _ := strconv.Atoi(stk[len(stk)-1])
            stk = stk[:len(stk)-1] // 将数字 pop 出栈
            t := strings.Repeat(getString(sub), repTime)
            stk = append(stk, t) // 重新入栈
            ptr++
        }
    }

    return getString(stk)
}

复杂度分析

chiehw commented 1 year ago

思路

用栈实现类似计算器的操作

代码

class Solution {
public:
    string decodeString(string s) {
        string res = "";
        stack <int> nums;
        stack <string> strs;
        int num = 0;
        int len = s.size();
        for(int i = 0; i < len; ++ i)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                num = num * 10 + s[i] - '0';
            }
            else if((s[i] >= 'a' && s[i] <= 'z') ||(s[i] >= 'A' && s[i] <= 'Z'))
            {
                res = res + s[i];
            }
            else if(s[i] == '[')
            {
                nums.push(num);
                num = 0;
                strs.push(res); 
                res = "";
            }
            else
            {
                int times = nums.top();
                nums.pop();
                for(int j = 0; j < times; ++ j)
                    strs.top() += res;
                res = strs.top(); 
                strs.pop();
            }
        }
        return res;
    }
};

复杂度

时间复杂度:O(n) 空间复杂度:O(n)

RestlessBreeze commented 1 year ago

思路

通过栈实现。

代码

class Solution {
public:
    string decodeString(string s) {
        string res = "";
        stack <int> nums;
        stack <string> strs;
        int num = 0;
        int len = s.size();
        for(int i = 0; i < len; ++ i)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                num = num * 10 + s[i] - '0';
            }
            else if((s[i] >= 'a' && s[i] <= 'z') ||(s[i] >= 'A' && s[i] <= 'Z'))
            {
                res = res + s[i];
            }
            else if(s[i] == '[')
            {
                nums.push(num);
                num = 0;
                strs.push(res); 
                res = "";
            }
            else
            {
                int times = nums.top();
                nums.pop();
                for(int j = 0; j < times; ++ j)
                    strs.top() += res;
                res = strs.top(); 
                strs.pop();
            }
        }
        return res;
    }
};

复杂度分析

tzuikuo commented 1 year ago

思路

利用两个栈,一个存当前字符,一个存当前数量,遍历字符串,遇到字母,加入当前字符,遇到数字字符,当前数字10加上当前数字字符,遇到‘[’,将当前字母和数字入栈,归0,遇到’]‘,将栈顶字母弹出,栈顶字母+栈顶数量当前字符串=累计字符串;然后继续。

代码

class Solution {
public:
    string decodeString(string s) {
        int n=s.size();
        stack<string> stackstr;
        stack<int> stacknum;
        string curstr="";
        int curnum=0;
        for(int i=0;i<n;i++){
            if(s[i]>='0'&&s[i]<='9') curnum=curnum*10+(s[i]-'0');
            if(s[i]>='a'&&s[i]<='z') curstr+=s[i];
            if(s[i]=='['){
                stackstr.push(curstr);
                stacknum.push(curnum);
                curstr="";
                curnum=0;
            }
            if(s[i]==']'){
                string temp=curstr;
                for(int i=0;i<stacknum.top()-1;i++) curstr+=temp;
                curstr=stackstr.top()+curstr;
                stackstr.pop();
                stacknum.pop();
            }
        }
        return curstr;
    }
};

复杂度分析

liuajingliu commented 1 year ago

思路

  1. 将字符串从末尾开始遍历
  2. 遇到“]”入栈
  3. 拼接要出栈的字符串,遇到"["出栈
  4. "["后紧跟数据,累计最终的数字
  5. 将遍历后入栈的字符串出栈,进行反转拼接,得到最终结果

代码

/**
 * @param {string} s
 * @return {string}
 */
 var decodeString = function(s) {
    let stack = []; // 定义存储字符串的栈
    let str = ""; // 定义最终返回的字符串
    let num = ""; // 定义字符串重复的次数
    const length = s.length;
    for (let i = length - 1; i >= 0; i--) {
      console.log("s[i]", stack, i);
      if (s[i] >= "0" && s[i] <= "9") {
        // 解析出连续的数字
        while (s[i] >= "0" && s[i] <= "9") {
          num += s[i];
          i--;
          console.log("num", num);
        }
        stack.push(
          str.repeat(
            Number(
              num
                .split("")
                .reverse()
                .join("")
            )
          )
        ); // 拼接字符
        str = "";
        num = ""; //清空计数
        i++;
      } else if (s[i] === "[") {
        // 遇到"["时,将后续字符出栈
        let curStr = stack.pop();
        while (curStr !== "]") {
          str += curStr;
          curStr = stack.pop(); // 拼接出栈的字符串 "["后跟着的一定是数字
        }
      } else {
        // 将字符 或 "]"入栈
        stack.push(s[i]);
      }
    }
    return stack.reverse().join("");
  };

复杂度分析

BruceZhang-utf-8 commented 1 year ago

思路

代码

class Solution {
    public String decodeString(String s) {
        //声明一个栈,存放数字
        Stack<Integer> stackNum = new Stack<>();
        //声明一个栈,存放字符
        Stack<StringBuffer> stackStr = new Stack<>();
        //记录数字
        int num=0;
        StringBuffer buff = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            if(Character.isDigit(s.charAt(i))){
                num=num*10+s.charAt(i)-'0';
            }else if(s.charAt(i)=='['){
                //先将数字入栈
                stackNum.push(num);
                //把字符存起来
                stackStr.push(buff);
                //数字归0
                num=0;
                buff=new StringBuffer();

            }else if(s.charAt(i)==']'){
                //取出数字栈顶元素
                Integer pop = stackNum.pop();
                //取出栈顶的字符栈
                StringBuffer str = stackStr.pop();
                for (int j = 0; j < pop; j++) {
                    str.append(buff.toString());
                }
                buff=str;
            }else{
                buff.append(s.charAt(i));
            }

        }

        return buff.toString();
    }
}
mayloveless commented 1 year ago

思路

把字符压到栈里,遇到 ] 出栈到 [ 组成字符,继续出栈到非数字,组成数字,拼接字符串,当作一个完整字符,压栈,继续遍历

代码

var decodeString = function(s) {
  const stack = [];

  for (let i = 0; i < s.length; i++) {
    if (s[i] !== ']') {
        stack.push(s[i]);
        continue;
    }
    let temStr = '';
    while (stack[stack.length - 1] !== '[') {
         temStr = stack.pop() + temStr;
    }

    stack.pop();

    let numStr = '';
    while (stack.length && isNumber(stack[stack.length - 1])) {
        numStr =  stack.pop() + numStr;
    }
    const res = temStr.repeat(Number(numStr));
    stack.push(res);
  }
  return stack.join('')
};

const isNumber = (chr) => {
  const num = Number(chr);
  return num >=0 && num <=9;
}

复杂度分析

时间复杂度:O(n), 空间复杂度:O(n)

LiHua1997 commented 1 year ago

思路

模拟栈

代码

class Solution {
    int ptr;

    public String decodeString(String s) {
        LinkedList<String> stk = new LinkedList<String>();
        ptr = 0;

        while (ptr < s.length()) {
            char cur = s.charAt(ptr);
            if (Character.isDigit(cur)) {
                // 获取一个数字并进栈
                String digits = getDigits(s);
                stk.addLast(digits);
            } else if (Character.isLetter(cur) || cur == '[') {
                // 获取一个字母并进栈
                stk.addLast(String.valueOf(s.charAt(ptr++))); 
            } else {
                ++ptr;
                LinkedList<String> sub = new LinkedList<String>();
                while (!"[".equals(stk.peekLast())) {
                    sub.addLast(stk.removeLast());
                }
                Collections.reverse(sub);
                // 左括号出栈
                stk.removeLast();
                // 此时栈顶为当前 sub 对应的字符串应该出现的次数
                int repTime = Integer.parseInt(stk.removeLast());
                StringBuffer t = new StringBuffer();
                String o = getString(sub);
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 将构造好的字符串入栈
                stk.addLast(t.toString());
            }
        }

        return getString(stk);
    }

    public String getDigits(String s) {
        StringBuffer ret = new StringBuffer();
        while (Character.isDigit(s.charAt(ptr))) {
            ret.append(s.charAt(ptr++));
        }
        return ret.toString();
    }

    public String getString(LinkedList<String> v) {
        StringBuffer ret = new StringBuffer();
        for (String s : v) {
            ret.append(s);
        }
        return ret.toString();
    }
}