LeetCode 394. 字符串解码(栈)

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

编码规则为: 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”

这是自己的狗屎东西。

package PTA;

import sun.awt.SunHints;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
     //   BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        int t[] = new int[]{1,3,4,2,2};
        int ans =0;
        for(int i=1;i<=100;i++){
            ans +=i;
        }
        new Main().decodeString("3[a]2[bc]");
        System.out.println(new Main().decodeString("3[a2[c]]"));
    }
    public String decodeString(String s) {
        Deque<Integer> stack = new ArrayDeque<>();
        StringBuffer ans = new StringBuffer();
        for(int i=s.length()-1;i>=0;i--){

            if(s.charAt(i)==']'){
                int j=i-1;
                StringBuffer sb=new StringBuffer();
                StringBuffer sbnum=new StringBuffer();
                while(s.charAt(j)!='['){
                    sb.append(s.charAt(j));
                    j--;
                }
                sb.reverse();//因为是先存的后面要reverse一下
                j--;
                while(j>=0 && s.charAt(j)>='0' && s.charAt(j)<='9'){
                    sbnum.append(s.charAt(j));
                    j--;
                }
                i=j+1;//此时i正好对应数字
                for(int w=0;w<Integer.parseInt(sbnum.reverse().toString());w++){
                    ans.insert(0,sb);
                }

            }
        }
        return ans.toString();
    }
    }


题解的

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

看了题解自己写的,还是发现了很多问题
例如:栈中栈顶现在存的是’abc‘,其下面一个存的是‘x’,现在要将其取出来,在我们的代码中,取出来便是’abc‘,由于是由栈顶开始取的,所以取出来的是abcx,但是实际输出应该是xabc。
所以我们采取了反转一下来解决这个问题:
在这里插入图片描述
但是我们此时如果查看输出的话,其输出是xcba!!出问题了,所以在从栈中取出元素时,就要先反转一下,如果是多位字符串不反转就要出现上面‘’abc‘的问题,先反转一下,最后循环结束后再反转一下就可以了
用注释掉的代码就要出问题。!!题解的getStirng方法就是为了避免这个问题。

       tem.append(new StringBuffer(stack.pop()).reverse());
                   // tem.append(stack.pop());

该题还需要注意的是:在遍历字符串s的时候,其数字有可能是多位数例如:13[a],我们是需要读取13为数字!所以在进行数字判断时要注意!(最开始的狗屎代码也想到了,但是总是哪出问题改哪里,越改越乱,应该按照最开始的大体思路来!)

class Solution {
 public String decodeString(String s) {
        Deque<String> stack = new ArrayDeque<>();
        int index =0;
        while(index < s.length()){
            char ch = s.charAt(index);
            //如果当前字符是数字
            if(Character.isDigit(ch)){
                StringBuffer t = new StringBuffer();
                t.append(ch);
                index++;
                //判断是否为多位数
                while(Character.isDigit(s.charAt(index))){
                    t.append(s.charAt(index));
                    index++;
                }
                //t不用反转
                stack.push(t.toString());

            }else if(Character.isLetter(ch) || ch=='['){
                //如果当前字符是字母(包括大写和小写字母)或 '['
                stack.push(ch+"");
                index++;
            }else{
                //如果当前字符是']'
                StringBuffer tem = new StringBuffer();
                while(!stack.isEmpty() &&!stack.peek().equals("[")){
                    //当是字母且stack不为空时,就加入到tem中
                    //其实也可以不用判断为空,因为其输入格式必为: 3[a] 这种形式,必定数字先进栈再是[进栈,所以判断时栈中必定有[
                         tem.append(new StringBuffer(stack.pop()).reverse());
                   // tem.append(stack.pop());
                }
                //反转一下顺序
                tem.reverse();
                //当前stack匹配到的是[,[前一个必定为数字,现在我们要提出数字
                stack.pop();//删除[,现在栈顶便是数字
                StringBuffer t = new StringBuffer();
                for(int w =0;w<Integer.parseInt(stack.peek());w++){
                    t.append(tem);
                }
                //删除栈顶数字
                stack.pop();
                stack.push(t.toString());
             
                index++;

            }
        }
        StringBuffer ans  = new StringBuffer();
        //这种方式是默认从栈顶进行遍历,但是栈底的字符串应该先输出,故该方式不行
//        for(String t : stack){
//
//            ans.append(t);
//        }
        while(!stack.isEmpty()){
            ans.append(stack.removeLast());//栈顶表示first,栈底表示last
        }

        return ans.toString();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超好的小白

没体验过打赏,能让我体验一次吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值