字符串解码[括号匹配问题怎么解决_json字符串带括号

字符串解码[括号匹配问题怎么解决_json字符串带括号对于括号匹配问题,典型的解法就算递归进行括号匹配,当然也可以栈模拟。在此基础上才能完成额外的操作,解答任何括号匹配问题。

字符串解码[括号匹配问题]"

前言

对于括号匹配问题,典型的解法就算递归进行括号匹配,当然也可以栈模拟。在此基础上才能完成额外的操作,解答任何括号匹配问题。

一、字符串解码

image.png

二、括号匹配问题

1、栈模拟–从左到右

// 字符串解码
public class DecodeString {
    /* 括号匹配问题,可以递归,也可栈模拟。 */
    // 栈模拟
    /* 栈中存stringbuilder。 碰到‘[’时,入栈一个空stringbuilder; 碰到‘]’,将栈顶的stringbuilderappend到上一个stringbuilder中; 碰到普通字符时,将字符加入栈顶stringbuilder中。 如果从前往后遍历,则需要用一个栈把'['前的数字存在栈中;如果从后往前遍历,则不用。 */
    public String decodeString(String s) {
        // 申请存字符和倍数的栈
        Stack<StringBuilder> strSK = new Stack<>();
        Stack<Integer> intSK = new Stack<>();
        // 初始化两个栈
        strSK.push(new StringBuilder());
        intSK.push(1);
        // 遍历字符串
        while (idx < s.length()) {
            char ch = s.charAt(idx++);
            // 如果ch是'[',则idx++(上面统一idx++了!),将新stringbuilder入栈。
            if (ch == '[') {
                strSK.push(new StringBuilder());
            }
            // 如果ch是']',则idx++,将栈顶stringbuilder以一定倍数融入上一个stringbuilder中。
            else if (ch == ']') {
                // 以一定倍数融合。
                int size = intSK.pop();
                StringBuilder topSB = strSK.pop();
                StringBuilder peekSB = strSK.peek();
                for (int i = 0; i < size; i++) peekSB.append(topSB.toString());
            }
            // 如果是普通字符,则加入topSB即可。
            else if (Character.isLetter(ch)) strSK.peek().append(ch);
                // 如果是数字,则需要获取该数有多大,并加入倍数栈中。
            else {
                int n = getNum(s, ch - '0');

                intSK.push(n);
            }
        }
        return strSK.peek().toString();
    }

    int idx = 0;// 遍历字符串的下标。

    // 采用10倍扩容法来获取数字大小。
    private int getNum(String s, int num) {

        while (idx < s.length() && Character.isDigit(s.charAt(idx))) num = num * 10 + s.charAt(idx++) - '0';

        return num;
    }

}

2、栈模拟–从右到左

// 如果是倒序,就不用倍数栈了,每次拿到'['时,取后面的倍数即可,最后做一个翻转。
class DecodeString2 {
    /* 括号匹配问题,可以递归,也可栈模拟。 */
    // 栈模拟
    /* 栈中存stringbuilder。 碰到‘[’时,入栈一个空stringbuilder; 碰到‘]’,将栈顶的stringbuilderappend到上一个stringbuilder中; 碰到普通字符时,将字符加入栈顶stringbuilder中。 如果从前往后遍历,则需要用一个栈把'['前的数字存在栈中;如果从后往前遍历,则不用。 */
    public String decodeString(String s) {
        // 初始化全局变量。
        init(s);
        // 申请存字符和倍数的栈
        Stack<StringBuilder> strSK = new Stack<>();
        // 初始化两个栈
        strSK.push(new StringBuilder());
        // 遍历字符串
        while (idx >= 0) {
            // 获取字符,统一idx--;
            char ch = s.charAt(idx--);
            // 如果ch是']',将新stringbuilder入栈。
            if (ch == ']') strSK.push(new StringBuilder());
            // 如果ch是']',则idx--,将栈顶stringbuilder以一定倍数融入上一个stringbuilder中。
            if (ch == '[') {
                // 以一定倍数融合。
                int size = getNum();
                StringBuilder topSB = strSK.pop();
                StringBuilder peekSB = strSK.peek();
                for (int i = 0; i < size; i++) peekSB.append(topSB.toString());
            }
            // 如果是普通字符,则加入topSB即可。
            if (Character.isLetter(ch)) strSK.peek().append(ch);

        }
        return strSK.peek().reverse().toString();
    }

    // 初始化全局变量
    private void init(String s) {
        this.s = s;
        this.idx = s.length() - 1;
    }

    String s;
    int idx;// 遍历字符串的下标。

    // 采用10倍扩容法来获取数字大小。
    private int getNum() {
        int num = 0;
        int n = 1;

        while (idx >= 0 && Character.isDigit(s.charAt(idx))) {
            num += (s.charAt(idx--) - '0') * n;

            n *= 10;
        }

        return num;
    }
}

3、递归匹配

// 碰到'['则递归,并传入前面的参数。
class DecodeString3 {
    /* 括号匹配问题,可以递归,也可栈模拟。 */
    // 栈模拟
    /* 栈中存stringbuilder。 碰到‘[’时,入栈一个空stringbuilder; 碰到‘]’,将栈顶的stringbuilderappend到上一个stringbuilder中; 碰到普通字符时,将字符加入栈顶stringbuilder中。 如果从前往后遍历,则需要用一个栈把'['前的数字存在栈中;如果从后往前遍历,则不用。 */
    public String decodeString(String s) {
        // 初始化全局变量。
        init(s);
        // 递归解决。
        return dfs(1).toString();
    }

    public StringBuilder dfs(int size) {
        StringBuilder sb = new StringBuilder();

        int n = 1;
        while (idx < s.length() && s.charAt(idx) != ']') {
            char ch = s.charAt(idx++);
            // 碰到'[',递归得到StringBuilder对象,并融入该层sb.
            if (ch == '[') sb.append(dfs(n));
            // 碰到数字,得到数字,更新n值。
            if (Character.isDigit(ch)) n = getNum(ch - '0');
            // 碰到普通字符,自己append加入。
            if (Character.isLetter(ch)) sb.append(ch);
        }
        // 碰到']',或者访问完成了。
        ++idx;
        // 字符放大,并返回。
        StringBuilder rs = new StringBuilder();
        for (int i = 0; i < size; i++) rs.append(sb.toString());

        return rs;
    }

    // 初始化全局变量
    private void init(String s) {
        this.s = s;
    }

    String s;
    int idx = 0;// 遍历字符串的下标。

    // 采用10倍扩容法来获取数字大小。
    private int getNum(int num) {

        while (idx < s.length() && Character.isDigit(s.charAt(idx))) num = num * 10 + s.charAt(idx++) - '0';

        return num;
    }
}

总结

1)括号匹配问题,可递归匹配,也可栈模拟。对于栈模拟,需要知道栈里存储些什么。

2)一题多解,融合贯通,会发现不一样的bug,训练出严谨的逻辑,沉淀更多知识点。

参考文献

[1] LeetCode 字符串解码

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13906.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注