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

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 4 】2021-09-13 - 394. 字符串解码 #13

Open azl397985856 opened 3 years ago

azl397985856 commented 3 years 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"

Weisday commented 3 years ago

代码

class Solution {
public:
    string decodeString(string s) {
        if(s.empty())
            return "";

        string ans;
        int i = 0;
        int len = s.length();
        int c = 0;
        while (isdigit(s[i]) && i < len)
            c = c * 10 + (s[i++] - '0');

        int j = i;
        if (i < len && s[i] == '[')
        {
            int open = 1;
            while (++j < len && open)
            {
                if (s[j] == '[') ++open;
                if (s[j] == ']') --open;
            }
        }
        else
        {
            while (j < len && isalpha(s[j])) 
                ++j;
        }

        if (i == 0)
            return s.substr(0, j) + decodeString(s.substr(j));

        string ss = decodeString(s.substr(i + 1, j - i - 2));
        while (c--)
            ans += ss;
        ans += decodeString(s.substr(j));
        return ans;
    }
};
nekomoon404 commented 3 years ago

【思路1——用栈来辅助匹配】

栈用来解决括号匹配问题一直可以的,题目中由于涉及字符串的多次拼接,可以开一个存字符串的栈;字符串重复的次数可以再用一个存数字的栈。

初始化 string str = ""int multi = 0, 从左向右遍历字符串中的元素:

  1. 如果是数字,就累积到 multi 上,因为可能是给多位数字,即用多个数字字符表示一个整数;
  2. 如果是字母,就接到str后面;
  3. 如果是左括号,因为在之后的操作中['左边的这部分字符串是不会发生变化的,那我们把str压到字符串栈中,再把multi压到数字栈中;之后再次初始化它们;
  4. 如果是右括号,则当前str中保存的就是括号内的字符串,因为在遇到左括号时str已“归零”, 那我们弹出字符串栈的栈顶,就是左括号前面的字符串last_str,弹出数字栈的栈顶multi,则当前解码的字符串就等于last_str + str * multi
string decodeString(string s) {
    stack<int> num_stk;
    stack<string> str_stk;

    int multi = 0;
    string str = "";
    for(auto ch : s) {
        if(isdigit(ch)){
            multi = multi * 10 + ch - '0';
        }
        else if(isalpha(ch)){
            str += ch;
        }
        else if(ch == '[') {
            num_stk.push(multi);
            str_stk.push(str);
            str = "";
            multi = 0;
        }
        else if(ch == ']') {
            string last_str = str_stk.top();
            str_stk.pop();
            int cur_multi = num_stk.top();
            num_stk.pop();
            while(cur_multi--){
                last_str += str;
            }
            str = last_str;
        }
    }
    return str;
}

时间复杂度: $O(N)$,遍历一次字符串。

空间复杂度: 栈的空间最坏情况下是$O(N)$,如2[2[2[a]]]

StefanLeeee commented 3 years ago

思路

代码

package com.leetcode;

import java.util.Collections;
import java.util.LinkedList;

/**
 * @author Enbing
 * @create 2021-09-13 8:30 PM
 * @Description
 */
public class T394 {
    int ptr;
    public String decodeString(String s) {
        LinkedList<String> stk = new LinkedList<>();
        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<>();
                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(S+∣s∣),即 O(S)O(S) 空间复杂度:O(S)

biscuit279 commented 3 years ago

思路

迭代法,遇到 ] 前不断入栈,然后出栈直到遇到数字。遇到数字就重复,再压入栈中。重复出栈操作直到碰到[

class Solution(object):
    def decodeString(self, s):
        """
        :type s: str
        :rtype: str
        """
        stack = []
        for c in s:
            if c== ']':
                repstr=''
                repcount=''

                #遇到 [ 前不断出栈
                while stack and stack[-1] != '[':
                    repstr = stack.pop() + repstr
                #pop出'['
                stack.pop()
                #遇到数字就相加(字符串格式)
                while stack and stack[-1].isnumeric():
                    repcount = stack.pop() + repcount
                stack.append(repstr * int(repcount))
                #不是]直接入栈
            else:
                stack.append(c)
        return "".join(stack)

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

Draculabo commented 3 years ago

思路: 因为方括号可能内嵌,需从最内层decode,可使用一个辅助栈:

  1. 将字符依次入栈,遇到第一个']'时出栈,至第一个'['前的数字截止.
  2. 根据数字解码得到相应的字符串。
  3. 将完成解码后的字符串重新入栈。
  4. 重复1-3中操作。 代码部分:

class Solution { public String decodeString(String str) {

    if (str == null || str.length() == 0) {
        return "";
    }

    Stack<Character> stack = new Stack<>();

    for (char c : str.toCharArray()) {
        if (c != ']') {
            stack.push(c);
            // 遇到']'
        } else {
            StringBuilder sb = new StringBuilder();
            while (!stack.isEmpty() && Character.isLetter(stack.peek())) sb.insert(0, stack.pop());

            String str = sb.toString();
            stack.pop();
            sb = new StringBuilder();
            while (!stack.isEmpty() && Character.isDigit(stack.peek())) sb.insert(0, stack.pop());

            int i= Integer.valueOf(sb.toString());
            while (i> 0) {
                for (char cc : str.toCharArray()) stack.push(cc);
                i--;
            }
        }
    }

    StringBuilder res = new StringBuilder();
    while (!stack.isEmpty()) res.insert(0, stack.pop());

    return res.toString();
}

}

复杂度: Time: O(n^2) Space: O(n)

baoqin87 commented 3 years ago

思路

使用入栈出栈操作,将原字符串解码

代码 JavaScript

var decodeString = function(s) {
  let res = '';
  let multi = 0;
  let stack_multi = [];
  let stack_res = [];
  for (let i = 0, len = s.length; i < len; i++) {
    c = s.charAt(i)
    if(c == '[') {
      // 把数字和拼接的字母分别压入栈
      stack_multi.push(multi)
      stack_res.push(res)
      multi = 0
      res = ''
    } else if(c == ']') {
      let tmp = ''
      // 数字出栈
      let cur_multi = stack_multi.pop()
      // 数字作为循环次数
      for (let i = 0; i < cur_multi; i++) {
        tmp += res
      }
      res = stack_res.pop() + tmp
    } else if (c >= '0' && c <= '9') {
      multi = multi * 10 + parseInt(c)
    } else {
      res += c
    }
  }
  return res;
}

复杂度分析

ymwang-2020 commented 3 years ago

思路

数据压栈和出栈

关键点

括号套括号的处理

代码

python3

class Solution:
    def decodeString(self, s: str) -> str:
        stack=[]
        num_str = ''
        k = 0
        for item in s:
            if item.isdigit():
                # 如果是数字就记录数字
                k = k * 10 + int(item)
            elif item == '[':
                #如果遇到左括号就压入 括号前数字 和 已处理好的字符
                stack.append((num_str,k))
                num_str=''#记录下一次的 括号内字符 或 普通字符
                k=0
            elif item==']':
                #遇到右括号则弹出,加上当前处理的方括号内字符*存储的K
                inner=stack.pop()
                num_str = num_str*inner[1]+inner[0]
            else:
                num_str += item

        return num_str

复杂度分析

令 n 为数组长度。

thisjustsoso commented 3 years ago

class Solution { public String decodeString(String s) { Stack stack=new Stack<>(); for(char c : s.toCharArray()){ if(c !=']'){ //遍历到‘]’之前一直压栈 stack.push(c); }else{ //取最里面[]内的字符 StringBuilder sub=new StringBuilder(); while(!stack.isEmpty() && Character.isLetter(stack.peek())){ sub.insert(0,stack.pop()); } //去掉‘]’ stack.pop(); //取重复次数 StringBuilder digitSb=new StringBuilder(); while(!stack.isEmpty() && Character.isDigit(stack.peek())){ digitSb.insert(0,stack.pop()); } int count=Integer.valueOf(digitSb.toString());

            while(count > 0){
                for(char ch : sub.toString().toCharArray() ){
                stack.push(ch);

                }
                count--;
            }
        }
    }
    StringBuilder sb=new StringBuilder();
    while(!stack.isEmpty()){
        sb.insert(0,stack.pop());
    }
return sb.toString();
}

}

potatoMa commented 3 years ago

思路


使用栈对字符串进行记录,在出现"]"之前,将"["、数字及字母推入栈中。出现了"]"之后,先找出"["顶部的所有字母,再找出"["底部的数字,将前面找出的字母以数字的倍数推入栈中。然后继续遍历,最终得出结果。

JavaScript代码


/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function(s) {
    if (!s.includes('[')) return s;
    const stack = [];
    for (let c of s) {
        if (c !== ']') {
            stack.push(c);
        } else {
            const temp = [];
            let top = stack.pop();
            while (top !== '[') {
                temp.unshift(top);
                top = stack.pop();
            }
            let count = '';
            while (!isNaN(stack[stack.length - 1])) {
                count = `${stack.pop()}${count}`;
            }
            while (count > 0) {
                stack.push(...temp);
                count--;
            }
        }
    }
    return stack.join('');
};

复杂度分析


时间复杂度:O(S + |s|) = O(S);

空间复杂度:O(S)

AnkiDord commented 3 years ago

思路

相出了存在子问题,但是不会写代码 去看了答案,第一种理解了,递归子问题代码还是不怎么理解

设置一个栈stack,字符串res和一个整数变量multi,遍历s,当字符是数字时变成整数(单个字符数字大小在0~9,可能连续出现多个),是‘['时将res和multi进栈 ,是‘]’时将之前的res和multi弹出,与当前res相加

代码

''' class Solution: def decodeString(self, s: str) -> str:

    stack, res, multi = [], '', 0
    for c in s:
        if c == '[':
            stack.append([res, multi])
            res, multi = '', 0
        elif c == ']':
            last_res, multi = stack.pop()
            res = last_res + multi*res
            multi = 0
        elif '0' <= c <= '9':
            multi = multi*10 + int(c)
        else:
            res += c
    return res

''' 时间复杂度:遍历字符串O(N) 空间复杂度:栈+字符串长度=O(N)

Tomtao626 commented 3 years 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)
  • 时间: O(N)
Gaozizhong commented 3 years ago

思路

字符串从前到后用栈进行处理

代码:Go

func decodeString(s string) string {
    stack := []string{}
    pointer := 0
    for pointer < len(s) {
        current := s[pointer]
        if current >= '0' && current <= '9' {
            digits := getDigits(s, &pointer)
            stack = append(stack, digits)
        } else if (current >= 'a' && current <= 'z') || (current >= 'A' && current <= 'Z') || current == '[' {
            stack = append(stack, string(current))
            pointer++
        } else {
            pointer++
            sub := []string{}
            for stack[len(stack)-1] != "[" {
                sub = append(sub, stack[len(stack)-1])
                stack = stack[:len(stack)-1]
            }
            for i := 0; i < len(sub)/2; i++ {
                sub[i], sub[len(sub)-i-1] = sub[len(sub)-i-1], sub[i]
            }
            stack = stack[:len(stack)-1]
            repTime, _ := strconv.Atoi(stack[len(stack)-1])
            stack = stack[:len(stack)-1]
            t := strings.Repeat(getString(sub), repTime)
            stack = append(stack, t)
        }
    }
    return getString(stack)
}

func getDigits(s string, pointer *int) string {
    digits := ""
    for ; s[*pointer] >= '0' && s[*pointer] <= '9'; *pointer++ {
        digits += string(s[*pointer])
    }
    return digits
}

func getString(v []string) string {
    result := ""
    for _, s := range v {
        result += s
    }
    return result
}

时间复杂度

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

yj9676 commented 3 years ago

[TOC]

LC394 字符串解码 [Medium]

Decode String

Solution

class Solution {
    public String decodeString(String s) {
        Stack<Character> stack = new Stack<>();
        for (char c : s.toCharArray()){
            if (c != ']'){
                stack.push(c);
            }else{
                StringBuilder sb = new StringBuilder();
                while (!stack.isEmpty() && Character.isLetter(stack.peek())){
                    sb.insert(0, stack.pop());
                }
                String str = sb.toString();
                stack.pop();

                sb = new StringBuilder();
                while(!stack.isEmpty() && Character.isDigit(stack.peek())){
                    sb.insert(0, stack.pop());
                }
                int count = Integer.parseInt(sb.toString());

                while(count > 0){
                    for (char ch : str.toCharArray()){
                        stack.push(ch);
                    }
                    count--;
                }
            }
        }
        StringBuilder ans = new StringBuilder();
        while(!stack.isEmpty()){
            ans.insert(0, stack.pop());
        }
        return ans.toString();
    }
}

复杂度分析


思路2 [DFS]

使用递归(DFS)后续复习递归补上

Solution

//Todo
fengchen321 commented 3 years ago

思路

官方题解

代码

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)

Moin-Jer commented 3 years ago

思路


使用栈存储未匹配的字符

代码


class Solution {
    public String decodeString(String s) {
        char[] ch = s.toCharArray();
        int len = ch.length;
        Deque<String> stack = new LinkedList<>();
        int num = 0;
        for (int i = 0; i < len; ++i) {
            if (ch[i] != ']') {
                if (ch[i] >= '0' && ch[i] <= '9') {
                    num = num * 10 + ch[i] - '0';
                } else if (ch[i] == '[') {
                    stack.push(num + "");
                    stack.push(ch[i] + "");
                    num = 0;
                } else {
                    stack.push(ch[i] + "");
                }
            } else {
                String str = "";
                while (!"[".equals(stack.peek())) {
                    str = stack.pop() + str;
                }
                stack.pop();
                int n = Integer.parseInt(stack.pop());
                String res = "";
                for (int j = 0; j < n; ++j) {
                    res += str;
                }
                stack.push(res);
            }
        }
        String ans = "";
        while (!stack.isEmpty()) {
            ans = stack.pop() + ans;
        }
        return ans;
    }
}

复杂度分析


yingliucreates commented 3 years ago

link:

https://leetcode.com/problems/decode-string/

代码 Javascript

const decodeString = function (str) {
  let stack = [];
  let currStr = "";
  let currNum = 0;

  for (let i = 0; i < str.length; i++) {
    if (str[i] === "[") {
      stack.push(currStr);
      stack.push(currNum);
      currStr = "";
      currNum = 0;
    } else if (str[i] === "]") {
      let prevNum = stack.pop();
      let prevStr = stack.pop();
      currStr = prevStr + currStr.repeat(prevNum);
    } else if (str[i] >= "0" && str[i] <= "9") {
      currNum = currNum * 10 + Number(str[i]);
    } else {
      currStr += str[i];
    }
  }
  return currStr;
};

复杂度分析

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

codingcai commented 3 years ago

思路

使用栈思想 保存number

代码

class Solution {
public:
    string decodeString(string s) {
        // 存放[之前的内容字符串内容
        stack<string> chars;
        //存放[之前的数字内容
        stack<int> numbers;
        string res = "";
        int num = 0;
        for (char one : s) {
            if (isdigit(one)) {
                num = num * 10 + one - '0';
            } else if (isalpha(one)) {
                res.push_back(one);
            } else if (one == '['){
                numbers.push(num);
                num = 0;
                chars.push(res);
                res = "";
            } else if (one == ']') {
                string tmp = res;
                for (int i = 0; i < numbers.top() - 1; ++i) {
                    res += tmp;
                }
                // 这里需要注意顺序
                res = chars.top() + res;
                chars.pop();numbers.pop();
            }
        }
        return res;
    }
};

复杂度

时间复杂度 O(n) 只需要遍历一遍 空间复杂度 O(n) 保存numbers 或者字符串

shawncvv commented 3 years ago

思路

按照官方题解思路

代码 Python

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)

复杂度

bingyingchu commented 3 years ago

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

        for i in range(len(s)):
            if s[i] == "]":
                letters = ''
                count = ''
                while stack and stack[-1] != "[":
                    letters = stack.pop() + letters
                stack.pop()
                while stack and stack[-1].isnumeric():
                    count = stack.pop() + count
                stack.append(int(count) * letters)

            else:
                stack.append(s[i])

        return ''.join(stack)

Time and Space: O(n) where n is the length of s
chanceyliu commented 3 years ago

思路

从前往后遍历字符串,依次推入栈中,直到遇到 ] ,就开始解析栈内的字符,直到遇到 [ ,就代表字符解析完成了,前方可能有数字或字母,直到遇到非数字,将之前得到数字*字符,得到解析后的字符,推入栈中,继续如此循环

代码

/**
 * @param {string} s
 * @return {string}
 */
function decodeString(s) {
  let stack = [];
  for (const i of s) {
    // 只要值不等于 "]" ,就只做入栈操作
    if (i !== "]") {
      stack.push(i);
      continue;
    }
    // 出现 "]" 了,那么他上一个元素必然为字母,那么在遇到 "[" 之前都只做拼接字符串的操作
    let str = "";
    // 从栈中拿出一个
    let value = stack.pop();
    while (value !== "[") {
      str = value + str;
      // 拼接完后在拉一个出来
      value = stack.pop();
    }
    // 匹配到 "[" ,所以跳出了上一个循环,我们在拉一个覆盖掉 "["
    value = stack.pop();
    //出现 "[" 了,那么他前面的元素肯定是数字或者字母,是数字的话我们就要再次拼接
    let num = "";
    while (!isNaN(value)) {
      num = value + num;
      // 继续出栈
      value = stack.pop();
    }
    // 出现新的字母了,上面把它出栈了,现在重新把它装回去,等待再次拼装
    stack.push(value);
    // 将处理拼接后的字符推入栈中,继续循环
    stack.push(str.repeat(num));
  }
  return stack.join("");
}

复杂度分析

Alanwgy commented 3 years ago

''' 1.所有可能的输入有 -,'[',']',数字,字母 2.做一个s的for循环,当发现是数字时,如果超过一位数,那么就会被乘以10 3.如果是一个字符,就会被添加金curString 4.如果遇到了'[',这是一个新的子串的开始,前面的子串都已经被处理了,所以将当前的curString和curNum附加到栈中, 并且将curString设为空,curNum设为0 5.当遇到']',到达了子串完整的地方,就是开始计算了 '''


class Solution:
    def decodeString(self, s: str) -> str:
        stack,curNum,curString = [],0,''
        for i in s:
            if i == '[':
                stack.append(curString)
                stack.append(curNum)
                curString = ''
                curNum = 0
            elif i == ']':
                num = stack.pop()
                prevString = stack.pop()
                curString = prevString + num*curString
            elif i.isdigit():
                curNum = curNum*10 + int(i)
            else:
                curString += i
        return curString
xingkong1994 commented 3 years ago

思路

目前写出的方法有点耗时,明天优化下, 1、采用递归的方式,每次只解码一个【】内的内容。

代码

class Solution {
public:
    string decodeString(string s) {
        if (s.empty())  return s;
        int idx_left_new = -1;
        int idx_left_old = -1;
        int idx_right = -1;
        string num;
        for (int i = 0; i < s.length(); i++) {
            if (s[i] == '[')  {
                idx_left_old = idx_left_new;
                idx_left_new = i;
            }
            if (s[i] == ']') {
                idx_right = i;
                break;
            }
        }
        int start;
        if (idx_left_old == -1) {
            for (int i = 0; i < idx_left_new; i++) {
                if (s[i] >= '0' && s[i] <= '9') {
                    start = i; break;
                }
            }
        } else {
            for (int i = idx_left_old + 1; i < idx_left_new; i++) {
                if (s[i] >= '0' && s[i] <= '9') {
                    start = i; break;
                }
            }
        }
        num = s.substr(start, idx_right - start);
        if (idx_left_new <= 0 || idx_right == -1)  return s;
        if (idx_right - idx_left_new == 1)  return s;
        string tmp;
        for (int i = 0; i < atoi(num.c_str()); i++) {
            tmp += s.substr(idx_left_new + 1, idx_right - idx_left_new - 1);
        }
        string tmp_s;
        if (idx_right != s.length() - 1) {
            tmp_s = start == 0? tmp + s.substr(idx_right + 1) : 
                s.substr(0, start) + tmp + s.substr(idx_right + 1);
        } else {
            tmp_s = start == 0? tmp: s.substr(0, start) + tmp;

        }
        return decodeString(tmp_s);
    }
};

复杂度

时间复杂度:O(n*k),n表示字符串的长度, k表示'['的个数。

方法二

思路

1、用栈的方法解决,只需遍历一次就够了

代码

class Solution {
public:
    string decodeString(string s) {
        if (s.empty())  return s;
        stack<int> numstack;
        stack<string> strstack;
        string cur = "";
        int num = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s[i] >= '0' && s[i] <= '9') {
                num = 10 * num + s[i] - '0';
            } else if (s[i] == '[') {
                numstack.push(num);
                num = 0;
                strstack.push(cur);
                cur.clear();
            } else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
                cur += s[i];
            } else if (s[i] == ']') {
                int count = numstack.top();
                numstack.pop();
                for (int i = 0; i < count; i++) {
                    strstack.top() += cur;
                }
                cur = strstack.top();
                strstack.pop();
            }
        }

        return cur;
    }
};
okbug commented 3 years ago

代码

CPP

class Solution {
public:
    string decodeString(string s) {
        string res;
        for (int i = 0; i < s.size();) {
            if (!isdigit(s[i])) res += s[i ++ ];
            else {
                int j = i;
                while (isdigit(s[j])) j++ ;
                int t = atoi(s.substr(i, j - i).c_str());
                int k = j + 1, sum = 0;
                while (sum >= 0) {
                    if (s[k] == '[') sum ++ ;
                    if (s[k] == ']') sum -- ;
                    k ++ ;
                }
                string str = decodeString(s.substr(j + 1, k - j - 2));
                while (t--) res += str;
                i = k;
            }
        }

        return res;
    }
};
cy-sues commented 3 years ago

代码

class Solution { public String decodeString(String s) { char[] chars = s.toCharArray(); Deque stackNum = new ArrayDeque<>(); Deque stack = new ArrayDeque<>(); StringBuilder sb = new StringBuilder(); int num = 0; for (int i = 0; i < chars.length ; i++) { if (chars[i] >= '0' && chars[i] <= '9') { num = num * 10 + Integer.parseInt(chars[i] + ""); //两位数以上的数字计算 } else if (chars[i] == '[') { stackNum.addLast(num); //不能在上一步加入数字队列,可能会有两位数以上的数字 stack.addLast(sb.toString()); //第一个待处理的字符串 sb = new StringBuilder(); //清空结果 num = 0; } else if (chars[i] == ']') { StringBuilder temp = new StringBuilder(); int n = stackNum.removeLast(); //上一步的结果,从栈弹出 while (n > 0) { temp.append(sb); n--; } sb = new StringBuilder(stack.removeLast() + temp); //更新原来的字符串结果 } else { sb.append(chars[i]); } } return sb.toString(); } }

linrAx commented 3 years ago

思路

遍历字符串,对不同情况做出相应操作

1、字符为数字,计算倍数

2、字符为字母,直接加到res

3、字符为左括号( '[' ),进行递归,递归的返回值为当前已遍历到的索引 i 和子字符串tmp 拿到返回值后将tmp乘以num后加到res中,并重置num

4、字符为右括号(']'),返回当前索引 i 以及在当前递归层的循环过程中生成的子字符串res

5、返回最终字符串res

代码

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)

空间复杂度 O(n)

leo173701 commented 3 years ago

思路:遇到字符匹配的事情,第一反应就是 用栈 来处理了。本题的关键在于“[” “]”, 这俩是判断入栈 还是 出栈 的关键。 时间复杂度: O(n) 空间复杂度:O(n) (其实用不到这么多空间,O(n) 算是最差的情况了)

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

    bracket_stack = []
    digit_stack = []
    res = ''
    n = ''
    for e in s:

        if e.isdigit():
            n+=e
        elif e == '[':
            bracket_stack.append(res)
            digit_stack.append(n)
            n = ''
            res = ''
        elif e == ']':

            res = (bracket_stack.pop() + res*int(digit_stack.pop()))
        else:
            res += e
    return res
bxcharlie commented 3 years ago
class Solution {
public:
    string decodeString(string s) {
        string res;
        stack<pair<int, string>> stk;
        int count = 0;
        for(auto c : s){
            if(isdigit(c)){
                 count = count*10 + (c-'0');
            }
        else if(c == '['){
            stk.push({count,res});
            count = 0;
            res = "";
        }
        else if(c == ']'){
            auto p = stk.top();
            stk.pop();
            string tmp = res;
            for(int i = 1; i < p.first; i++){
                res += tmp;
            }
            res = p.second + res;
        }
        else{
            res += c;
        }
    }
    return res;
    }
};
Zhi22 commented 3 years ago

思路

代码

class Solution:
    def decodeString(self, s: str) -> str:
        ans = []
        for ch in s:
            if ch == ']':
                cur_stack = []
                while ans[-1] != '[':
                    cur_stack.append(ans.pop())
                ans.pop()
                order = 1
                count = 0
                while ans and ans[-1].isnumeric():
                    count += (int(ans.pop()) * order)
                    order *= 10
                for _ in range(count):
                    ans.extend(cur_stack[::-1])
            else:
                ans.append(ch)
        return ''.join(ans)

算法复杂度

Venchyluo commented 3 years ago

注意分析遇到数字, 字母,'[', ']' 不同情况时如何处理。因为题目规定好,不会出现3[4],3a 这种情况,可以假定int[alphabet] 这样的顺序。
注意两个字符串, 一个是之前已经处理完毕,需要和现在的正在处理的字符串相加

class Solution:
    def decodeString(self, s: str) -> str:
        cur_string,times = '',0
        stack = []
        for char in s:
            if char.isdigit():
                times = times*10+int(char) 
                # 因为可能是多位数           
            elif char == '[':
                stack.append(cur_string)
                stack.append(times)   
                times,cur_string = 0,''
            elif char == ']':
                pre_times = stack.pop()
                pre_string = stack.pop()
                cur_string = pre_string + pre_times * cur_string         
            else:
                cur_string += char

        return cur_string

time complexity: O(N) space complexity: O(N)

JianXinyu commented 3 years ago
class Solution {
public:
    string decodeString(string s) {
        if(s.length() < 4)
            return s;

        stack<char> stk;
        for(char ch : s){
            if(ch != ']')
                stk.push(ch); // 除']'外,所有都入栈
            else{
                // 1. 取出[]内的字符串
                string str;

                while( !stk.empty() && isalpha(stk.top()) ){
                    str.insert(0, 1, stk.top());
                    stk.pop();
                }

                stk.pop(); // pop '['

                // 2. 得到倍数数字
                string num;
                 while( !stk.empty() && isdigit(stk.top()) ){
                    num.insert(0, 1, stk.top());
                    stk.pop();
                }
                int count = stoi(num);

                // 3. 根据倍数把字母再push回去
                while( count > 0 ){
                    for( char chr : str){
                        stk.push(chr);
                    }
                    count--;
                }
            }
        }
        // 取出栈里的所有char
        string ans;
        while( !stk.empty() ){
            ans.insert(0, 1, stk.top());
            stk.pop();
        }

        return ans;
    }
};
AaronConlon commented 3 years ago

思路

用栈接入字符串,遍历字符串,当匹配到字母和'['的时候就入栈保存,当匹配到']'的时候则保存当前的结果,最后得出结果

代码

const isNumber = (str: string) => /\d/.test(str);
const isLetter = (str: string) => /[a-z]/.test(str);

function decodeString(str: string): string {
  if (str.length === 0) return "";
  const stack = [];
  const len = str.length;
  let index = 0;
  let repeatStr = "";
  while (index < len) {
    if (isLetter(str[index]) || str[index] === "[") {
      stack.push(str[index]);
    } else if (isNumber(str[index])) {
      if (isNumber(stack[stack.length - 1])) {
        stack[stack.length - 1] += str[index];
      } else {
        stack.push(str[index]);
      }
    } else if (str[index] === "]") {
      let prevValue = stack.pop();
      while (prevValue !== "[") {
        repeatStr = prevValue + repeatStr;
        prevValue = stack.pop();
      }
      if (isNumber(stack[stack.length - 1])) {
        stack[stack.length - 1] = repeatStr.repeat(stack[stack.length - 1]);
      } else {
        stack.push(repeatStr);
      }
      repeatStr = "";
    }
    index++;
  }
  return stack.join("");
}

复杂度

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

CruiseYuGH commented 3 years ago

class Solution: def decodeString(self, s: str) -> str: stack = [] cur_num = 0 cur_str="" for c in s: if c.isdigit(): cur_num = cur_num10+int(c) elif c is "[": stack.append(cur_str) stack.append(cur_num) cur_str = '' cur_num = 0 elif c is "]": temp_num = stack.pop() temp_str = stack.pop() cur_str = temp_str + temp_num cur_str else: cur_str+=c return cur_str

lizzy-123 commented 3 years ago

思路:使用栈将带有数字的转为为字符串 `string decodeString(string s) { int n = s.size(); vector stk;

    for (int i = 0; i<n; i++)
    {
        char c = s[i];
        if (c == ']')
        {
            vector<string> subStr;
            while (stk.back() != "[")
            {
                subStr.push_back(stk.back());
                stk.pop_back();
            }
            stk.pop_back();
            string strNum = "";
            while (stk.size()>0&&stk.back()<="9"&&stk.back()>="0")
            {
                strNum = strNum+stk.back();
                stk.pop_back();
            }
            reverse(strNum.begin(), strNum.end());
            int k = stoi(strNum);
            //stk.pop_back();
            reverse(subStr.begin(), subStr.end());
            string tmp = "";
            for (int j = 0; j<subStr.size(); j++)
            {
                tmp += subStr.at(j);
            }
            string tmp1 = "";
            while (k--)
            {
                tmp1 = tmp1 + tmp;
            }
            stk.push_back(tmp1);
        }
        else
        {
            stk.push_back(string(1,c));
        }
    }
    string result = "";
    for (int m = 0; m<stk.size(); m++)
    {
        result += stk.at(m);
    }
    return result;
}`

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

ivalkshfoeif commented 3 years ago
class Solution {
    public String decodeString(String s) {
        Stack<Character> stack = new Stack();
        int repeatTimes = 0;
        char[] sChars = s.toCharArray();
        for (char sChar: sChars){
            if (sChar == ']'){
                char a = stack.pop();
                List<Character> temp = new ArrayList();
                while (a != '['){
                    temp.add(a);
                    a = stack.pop();
                }
                Collections.reverse(temp);

                List<Character> times = new ArrayList();
                char n = stack.pop();
                while (n >= '0' && n <='9'){
                    times.add(n);
                    if (stack.isEmpty()){
                        break;
                    }
                    n = stack.pop();
                }
                if (!(n >= '0' && n <= '9')){
                    stack.push(n);
                }
                Collections.reverse(times);
                for (char ch: times){
                    repeatTimes = repeatTimes * 10 + ch - '0';
                }

                for (int i = 0; i < repeatTimes; i++){
                    for (char ch: temp){
                        stack.push(ch);
                    }
                }
                repeatTimes = 0;
            }else {
                stack.push(sChar);
            }
        }
        StringBuilder ans = new StringBuilder();
        for (char ch: stack){
            ans.append(ch);
        }
        return ans.toString();
    }
}

写复杂了,但是打卡时间过了,直接交 O(N) O(N)

ychen8777 commented 3 years ago

思路

没注意到第2个 testcase 有嵌套,只考虑了没有嵌套的情况 \ 用 res, curString, curMultiplier 分别记录遍历到 s[i] 时的 最后结果,当前substring,以及当前substring需要重复的次数 \ 逢 '[' 记录multiplier \ 逢 ']' 将 curString 乘以倍数后append到 res,重置 curString, curMultiplier \

代码

class Solution {
    public String decodeString(String s) {

        if ("".equals(s)) {
            return "";
        }

        StringBuilder res = new StringBuilder("");
        StringBuilder curString = new StringBuilder("");
        StringBuilder curMultiplier = new StringBuilder("0");
        boolean isNumber = true;
        int multiplier = 0;

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

            char curChar = s.charAt(i);
            //System.out.println("isNumber: " + isNumber);

            if (curChar == '[') {
                multiplier = Integer.parseInt(curMultiplier.toString());
                // curMultiplier = new StringBuilder("0");
                //System.out.println("multiplier: " + curMultiplier + ", " + multiplier);
                isNumber = false;
                continue;
            }

            if (curChar == ']') {
                res.append(multiplyString(multiplier, curString.toString()));
                isNumber = true;
                //System.out.println("curString: " + curString.toString());
                curMultiplier = new StringBuilder("0");
                curString = new StringBuilder("");
                continue;
            }

            if (isNumber) {
                curMultiplier.append(curChar);
                //System.out.println("multiplier in isNumber: " + curMultiplier);
                continue;
            } else {
                curString.append(curChar);
                continue;
            }                   
        }

        return res.toString();

    }

    private String multiplyString(int num, String s) {
        StringBuilder res = new StringBuilder("");

        for (int i = 1; i <= num; i++) {
            res.append(s);
        }

        return res.toString();
    }
}

复杂度

时间: O(n) \ 空间: O(n)

BadCoderChou commented 3 years ago

代码

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)

空间复杂度 O(n)

dongzegithub commented 3 years ago

394. 字符串解码

思路

由括号匹配问题联想到此题亦可以使用栈来解决,主要思路为

  1. 遍历字符串,非]字符进栈
  2. 遇到]字符开始出栈
    • 出栈如果是字符,则记录,直到遇到[字符
    • 继续出栈,通过数字得到重复次数,直到遇到非数字字符
    • 将所有出栈记录的字符按解析的次数再压入栈中
  3. 如此循环,直到遍历完给定字符串
  4. 倒序输出栈中的字符即可

代码

public class CustomStack {
    private Stack<Integer> originStack = new Stack<>();

    private int[] incrementArr;

    private int maxSize;

    public CustomStack(int maxSize) {
        this.maxSize = maxSize;
        incrementArr = new int[maxSize];
    }

    public void push(int x) {
        if (originStack.size() >= maxSize) {
            return;
        }
        originStack.push(x);
        // 新元素入栈,清空之前增量数组中的缓存值
        incrementArr[originStack.size() - 1] = 0;
    }

    public int pop() {
        if (originStack.isEmpty()) {
            return -1;
        }
        int index = originStack.size() - 1;
        int origin = originStack.pop();
        if (index > 0) {
            incrementArr[index - 1] = incrementArr[index - 1] + incrementArr[index];
        }
        return origin + incrementArr[index];
    }

    public void increment(int k, int val) {
        if (k <= 0 || originStack.isEmpty()) {
            return;
        }
        int index = Math.min(originStack.size(), k) - 1;
        incrementArr[index] += val;
    }

    public int pop1() {
        if (originStack.empty()) {
            return -1;
        }
        int index = originStack.size() - 1;
        int origin = originStack.pop();
        // pop时,需要pop栈顶 + 增量数组当前值
        return origin + incrementArr[index];
    }

    public void increment1(int k, int val) {
        if (k <= 0) {
            return;
        }
        int capacity = Math.min(originStack.size(), k);
        for (int i = 0; i < capacity; i++) {
            incrementArr[i] += val;
        }
    }
}

复杂度分析

时间复杂度为O(N) 只遍历了一遍字符串,所以时间复杂度为O(N)

Shinnost commented 3 years ago

思路

字符'['作为入栈标志,字符']'作为出栈标志。每次出栈时拼接当前k[encoded_string]与上一个包含该k[encoded_string]k[encoded_string]的剩余部分,可假设最开始的字符串s由一个[]包裹,且已经完成入栈操作。即由最内层[]向外进行解码。

关键点:

实现(python)

# https://leetcode-cn.com/problems/decode-string/solution/decode-string-fu-zhu-zhan-fa-di-gui-fa-by-jyd/
class Solution:
    def decodeString(self, s: str) -> 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 + res * cur_multi
            elif '0' <= c <= '9':
                multi = multi * 10 + int(c)
            else:
                res += c
        return res

复杂度分析

  1. 时间复杂度:$O(n)$。共遍历一遍字符串。
  2. 空间复杂度:$O(n)$。
winterdogdog commented 3 years ago
/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function(s) {
    let stack = [];const reg = /[a-zA-Z]+|[0-9]+|\[|\]/g;;
    while(reg.lastIndex < s.length) {
        let count = reg.exec(s)[0]
        if (count !== ']') {
            stack.push(count)
        } else {
            let cha = stack.pop(), str = '';
            while(cha !== '[') {
                str = cha + str
                cha = stack.pop()
            }
            stack.push(str.repeat(+stack.pop()))
            console.log(stack)
        }
    }
    return stack.join('')
};
max-qaq commented 3 years ago

思路:括号嵌套,可以用栈

关键点:两个栈

代码:

class Solution {
    public String decodeString(String s) {
        Deque<Integer> numstack = new LinkedList<>();
        Deque<String> sstack = new LinkedList<>();
        StringBuilder res = new StringBuilder("");//结果
        int mult = 0;//倍数

        for(Character ch : s.toCharArray()){
            if(ch == '['){
                numstack.addLast(mult);
                sstack.addLast(res.toString());
                mult = 0;
                res = new StringBuilder("");
            }else if(ch == ']'){
                int cur_mult = numstack.removeLast();
                StringBuilder tempsb = new StringBuilder("");
                for(int i=0;i<cur_mult;i++){
                    tempsb.append(res.toString());
                }
                res = new StringBuilder(sstack.removeLast() +tempsb.toString() );
            }else if(ch >= '0' && ch <= '9'){
                mult = mult * 10 + Integer.parseInt(ch + "");
            }else{
                res.append(ch);
            }
        }
        return res.toString();
    }
}

复杂度分析:

时间复杂度:遍历一次,O(n)

空间复杂度:应该也是O(n) 自己独立做不出。。要加油啊

Okkband commented 3 years ago
class Solution {
private:
    string src;
    int 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] == ']'){
            return "";
        }
        char cur = src[ptr];
        int cnt = 1;
        string res;
        if (isdigit(cur)) {
            cnt = getDigits();
            ++ptr;
            string str = getString();
            ++ptr;
            while(cnt--){
                res += str;
            }
        } else if (isalpha(cur)){
            res = string(1, src[ptr++]);
        }
        return res + getString();
    }
public:
    string decodeString(string s) {
        src = s;
        ptr = 0;
        return getString();
    }
};

时间复杂度: O(N)

空间复杂度: O(N)

muimi commented 3 years ago

思路

使用两个栈一个存放数字,一个存放字符串

代码

class Solution {
  public String decodeString(String s) {
    Stack<Integer> intStack = new Stack();
    Stack<StringBuilder> strStack = new Stack();
    StringBuilder pattern = new StringBuilder();
    int number = 0;

    for (char ch : s.toCharArray()) {
      if (Character.isDigit(ch)) {
        number = number * 10 + ch - '0';
      } else if (ch == '[') {
        intStack.push(number);
        strStack.push(pattern);
        number = 0;
        pattern = new StringBuilder();
      } else if (ch == ']') {
        StringBuilder temp = pattern;
        pattern = strStack.pop();
        for (int i = intStack.pop(); i > 0; i--) pattern.append(temp);
      } else pattern.append(ch);
    }
    return pattern.toString();
  }
}

复杂度

Poidaze7 commented 3 years ago

394. 字符串解码

ChenJingjing85 commented 3 years ago

思路:

对字符串,数字, 左括号分别建立各自的栈, 遍历字符如各自的栈,字符为右括号时,每个栈分别弹出,计算重复字符串,若左括号栈不为空,得到的字符串继续入字符串栈,否则append到结果中。注意入栈时字符和字母的连续性,需要保留前一个字符做判断,判断是新入栈还是拼接到栈顶元素。同时建立辅助栈,记录数字前面一个字符,在字符串重复计算完后,判断是新入栈还是拼接到字符串栈的栈顶元素。

代码:

class Solution {
    public String decodeString(String s) {        StringBuilder sb = new StringBuilder();
        char[] chs = s.toCharArray();
        Stack<Character> bucks = new Stack();
        Stack<Integer> nums = new Stack();
        Stack<Character> numPres = new Stack();
        Stack<String> letters = new Stack();
        boolean isDigitBreak = false;
        boolean isLetterBreak = false;
        Character preChar = null;
        for(int i = 0; i < chs.length; i ++){
            char c = chs[i];
            if(bucks.isEmpty() && Character.isLetter(c)){
                sb.append(String.valueOf(c));
                isDigitBreak = false;
                isLetterBreak = true;
                preChar = c;
            }else if(Character.isDigit(c)){
                 int num = Integer.valueOf(String.valueOf(c));
                 if(preChar != null && Character.isDigit(preChar)){
                     int pre = nums.pop();
                     nums.push(pre*10+num);
                 }else{
                    nums.push(num);
                    numPres.push(preChar);
                 }

                 preChar = c;
            }else if(Character.isLetter(c)){
                String sc = String.valueOf(c);
                 if(preChar != null && Character.isLetter(preChar)){
                     String pre = letters.pop();
                     letters.push(pre+sc);
                 }else{
                    letters.push(sc);
                 }           
                 preChar = c;
            }else if(c == '['){
                bucks.push(c);
                preChar = c;
            }else if(c == ']'){
                bucks.pop();
                int num = nums.pop();
                Character numPre = numPres.pop();
                String letter = letters.pop();
                StringBuilder sbTemp = new StringBuilder();
                while(num>0){
                    sbTemp.append(letter);
                    num--;
                }
                String temp = sbTemp.toString();
                if(bucks.isEmpty()){
                    sb.append(temp);
                }else{
                    if(numPre != null && (Character.isLetter(numPre))){
                        String pre = letters.pop();
                        letters.push(pre+temp);
                    }else{
                        letters.push(temp);
                    }
                }
            }

        }
        return sb.toString();
    }
}

复杂度分析

bt2ee commented 3 years ago

思路

外层的解码需要等待内层解码的结果。

代码

/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function(s) {
  let numStack = []
  let strStack = []
  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 = ''
      numStack.push(num)
      num = 0
    } else if (char === ']') {
      let repeatTime = numStack.pop()
      result = strStack.pop() + result.repeat(repeatTime)
    } else {
      result += char
    }
  }
  return result
};

复杂度分析

时间复杂度 O(N),N 是解析后字符串的长度 空间复杂度 O(N)

LAGRANGIST commented 3 years ago

题目描述

394. 字符串解码

难度中等

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[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"

思路


代码

#include <iostream>
using namespace std;
#include <bits/stdc++.h>

/*
迭代实现思路:
    借助两个栈 stack <string> strs 和 stack <int> nums;
    并且将结果保存到字符串 ans 里面
    遍历 s: 
    1. 如果遇到数字则开始记录数字
    2. 如果遇到字母则 strs.top() += s[i] 
    3. 如果遇到 [ 则将记录的数字入栈,将其后面的字符串入栈直到遇到不是字母的东西
    4. 如果是 ‘ ] ' 则将栈顶的 nums.top( ) 倍的 strs.top( )加入到栈顶的后一个元素后面然后让其成为新的栈顶 

*/

string decodeString(string s)
{
    stack<int> nums;
    stack<string> strs;
    int multi = 0;
    string res = "";
    int i = 0;
    strs.push(res);
    while(i < s.length())
    {
        if (s[i] <= '9' && s[i] >= '0') //情况1
        {
            multi = 10 * multi + s[i] - '0';
            i++;
        }
        if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) //情况2
        {
            string to_be_added = strs.top();
            strs.pop();
            to_be_added += s[i];
            strs.push(to_be_added);
            i++;
        }
        if (s[i] == '[')
        {
            nums.push(multi);
            i++;
            multi = 0;
            string temp = "";   //清零很重要
            while ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) //将 [ 后面的字符部分入栈,
            {
                temp += s[i];
                ++i;
            }
            strs.push(temp);
            temp = "";//养成习惯,用来记录的变量用完后就清零(例如cnt,flag那些)
        }
        if(s[i] == ']')
        {
            string to_be_multiplied = strs.top();
            strs.pop();
            string to_be_added = strs.top();
            strs.pop();

            for (int i = 0; i < nums.top(); i++)
            {
                to_be_added += to_be_multiplied;
            }
            strs.push(to_be_added);//现在top就是相对来说最内层的了
            nums.pop();
            ++i;//这里一开始漏
        }

    }
    return strs.top();
}

//test drive
int main()
{
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);

    string input = "";
    cin >> input;
    cout << decodeString(input)<<endl;
    return 0;
}

复杂度分析

时间复杂度和空间复杂度均为 O( n )

xixvtt commented 3 years ago
zszs97 commented 3 years ago

开始刷题

题目简介

【Day 4 】2021-09-13 - (394. 字符串解码)

题目思路

题目代码

代码块

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

复杂度

jsyxiaoba commented 3 years ago

思路

两个栈解法 一个栈放倍数,一个栈放字母

js代码

var decodeString = function(s) {
    let numStack = []; // 存倍数的栈
    let strStack = []; // 存 待拼接的str 的栈
    let num = 0; // 倍数中转站
    let result = ''; // 字符串中转站
    for(const char of s){
        if(!isNaN(char)){ // 遇到数字
            num = num * 10 + (+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;
};

复杂度

wangwiitao commented 3 years ago

思路:

开括号前面的为数字,闭括号前面的为字符,遇到开括号前面可能大于个位数,用10*拼接

代码

/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function (s) {
    let numStack = [];
    let strStack = [];
    let num = 0;
    let result = "";
    for (let char of s) {
        if (!isNaN(char)) {
            num = num * 10 + Number(char);
        } else if (char === "[") {
            numStack.push(num);
            num = 0;
            strStack.push(result);
            result = "";
        }else if(char ==="]"){
            let repeatNum = numStack.pop();
            result = strStack.pop() + result.repeat(repeatNum);
        }else{
            result += char;
        }
    }
    return result;
};