[Leetcode]394.字符串解碼
阿新 • • 發佈:2019-03-04
思路 for change stl的stack 規則 sta 空格 題目 mage ,那麽22就是
題目與解釋
給定一個經過編碼的字符串,返回它解碼後的字符串。
編碼規則為: k[encoded_string]
,表示其中方括號內部的 encoded_string 正好重復 k 次。註意 k 保證為正整數。
你可以認為輸入字符串總是有效的;輸入字符串中沒有額外的空格,且輸入的方括號總是符合格式要求的。
此外,你可以認為原始數據不包含數字,所有的數字只表示重復的次數 k ,例如不會出現像 3a
或 2[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".
解釋:
這道實際上是一道字符串與棧結合的問題。如何看出是棧結合的問題呢?
- 有匹配(‘[‘和‘]‘)的情況,需要使用棧來完成匹配過程
- 有遞歸的情況, 如3[2[ab]]這樣
在匹配符號上,我參照我之前寫的小型計算器的符號匹配,遇到‘]‘就去尋找最近出現的匹配符號‘[‘。
思路
建立一個字符棧,這裏用的是STL自帶的stack<char>
逐個讀入字符壓入棧,當遇到‘]‘符號就尋找最近的匹配符號。
這個尋找的過程就是不斷判斷棧頂是否為‘[‘符號?
->否。這個是括號內的字符,暫時存入一個字符串ss
->是。則尋找到匹配的字符,繼續往前尋找‘[‘的字符前的所有"數字字符串",如34[22[ss]]
[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;
}
};
[Leetcode]394.字符串解碼