• [Leetcode]394.字符串解码


    题目与解释

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

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

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

    此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[4] 的输入。

    示例:

    s = "3[a![](https://img2018.cnblogs.com/blog/1575923/201903/1575923-20190304151000879-833294601.png)
    
    ]2[bc]", 返回 "aaabcbc".
    s = "3[a2[c]]", 返回 "accaccacc".
    s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
    

    解释:

    这道实际上是一道字符串与栈结合的问题。如何看出是栈结合的问题呢?

    1. 有匹配('['和']')的情况,需要使用栈来完成匹配过程
    2. 有递归的情况, 如3[2[ab]]这样

    在匹配符号上,我参照我之前写的小型计算器的符号匹配,遇到']'就去寻找最近出现的匹配符号'['。

    思路

    建立一个字符栈,这里用的是STL自带的stack<char>

    逐个读入字符压入栈,当遇到']'符号就寻找最近的匹配符号。

    这个寻找的过程就是不断判断栈顶是否为'['符号?

    ->否。这个是括号内的字符,暂时存入一个字符串ss

    ->是。则寻找到匹配的字符,继续往前寻找'['的字符前的所有"数字字符串",如34[22[ss]],那么22就是[ss]的数字字符串,34则是[22[ss]]的数字字符串。在寻找完后需要将这个字符串转换成实际的数字。

    经过一次上述过程后,已经知道一个括号内字符串和这段字符串出现的次数k。我们把k个字符串压入我们创建的字符栈。

    而当所有字符都读完了,则转换实际上就已经结束了。我们先根据思路写一段解法,但效率还不是很高。
    我们看看"3[a1[b]]"的图例

    class Solution {
    public:
    	string decodeString(string s) {
    		string ans = "";
    		stack<char>st;
            /*visit all the character in the string s*/
    		for (unsigned i = 0; i < s.length(); i++) {
    			if (s[i] != ']')st.push(s[i]);
    			else {
                     /*
                     if we find the character ']', it means we find a pair.
                     string ss means the string in the pair of this times.
                     string num means the number k in the pair of this times.
                     Initialize these two strings as an empty string.
                     */
    				string ss = "", num = "";
    				while (st.top() != '[') {
    					ss += st.top();
    					st.pop();
    				}
                     /*Delete '[' character*/
    				st.pop();
                     /*reverse the string ss*/
    				reverse(ss.begin(), ss.end());
    				while (!st.empty() && st.top() <= '9'&&st.top() >= '0') {
    					num += st.top();
    					st.pop();
    				}
    				unsigned times = 0, index = 1;
    				for (unsigned i = 0; i < num.length(); i++, index =index* 10) {
    					times += index * (num[i]-'0');
    				}
    				string sss ="";
    				for (unsigned i = 0; i < times; i++) {
    					sss += ss;
    				}
    				for (unsigned i = 0; i < sss.length(); i++) {
    					st.push(sss[i]);
    				}
    			}
    		}
            /* push the k times string to the stack st*/
    		while (!st.empty()) {
    			ans += st.top();
    			st.pop();
    		}
    		reverse(ans.begin(), ans.end());
    		return ans;
    	}
    };
    

    很暴力的按照思路的过程写了代码,优化点是可以自己写一个stack而不是使用STL的stack,使这个自己写的stack拥有遍历的方法。新增的内容有注释提示。能将上面代码优化4ms。

    /*********added below*********/
    class Stack {
    public:
    	Stack() {
    		topNum = -1;
    		ll.clear();
    	}
    	void push(char c) {
    		ll.push_back(c);
    		topNum++;
    	}
    	char top() {
    		return ll[topNum];
    	}
    	void pop() {
    		ll.pop_back();
    		topNum--;
    	}
    	bool empty() {
    		return topNum == -1;
    	}
    	vector<char>ll;
    private:
    	int topNum;
    };
    /******add above*********/
    class Solution {
    public:
    	string decodeString(string s) {
    		string ans = "";
    		Stack* st=new Stack();
    		for (unsigned i = 0; i < s.length(); i++) {
    			if (s[i] != ']')st->push(s[i]);
    			else {
    				string ss = "", num = "";
    				while (st->top() != '[') {
    					ss += st->top();
    					st->pop();
    				}
    				st->pop();
    				/*Delete '[' character*/
    				reverse(ss.begin(), ss.end());
    				while (!st->empty() && st->top() <= '9'&&st->top() >= '0') {
    					num += st->top();
    					st->pop();
    				}
    				unsigned times = 0, index = 1;
    				for (unsigned i = 0; i < num.length(); i++, index =index* 10) {
    					times += index * (num[i]-'0');
    				}
    				string sss ="";
    				for (unsigned i = 0; i < times; i++) {
    					sss += ss;
    				}
    				for (unsigned i = 0; i < sss.length(); i++) {
    					st->push(sss[i]);
    				}
    			}
    		}
            /******change below********/
    		for (char it : st->ll) {
    			ans += it;
    		}
            /******change above********/
            delete st;
    		return ans;
    	}
    };
    
  • 相关阅读:
    centos下网络的基本配置方法讲解
    win8.1环境下硬盘安装centos6.5双系统
    新人出世
    Docker 仓库管理
    Docker Dockerfile
    Docker image创建之Hello world
    ASP.Net Core 发布到 Centos Docker
    C# 人工智能
    C#使用ML.Net完成人工智能预测
    无监督和有监督算法的区别
  • 原文地址:https://www.cnblogs.com/adamwong/p/10470827.html
Copyright © 2020-2023  润新知