题目一
思路: 1.迭代
利用栈,令每个被括号包裹的子串返回一个 {元素名:出现次数} 的字典,汇总到上一层的字典中,统计结果。
class Solution { public: string countOfAtoms(string formula) { stack<map<string,int>>s = solve(formula); map<string,int>mp = s.top(); cout<<mp.size(); string ans = ""; for(auto t:mp){ ans += (t.second > 1 ? t.first + to_string(t.second):t.first); } return ans; } stack<map<string,int>> solve(string formula){ // 每一个括号包裹的子串都让返回一个 元素名:出现次数 的字典 stack<map<string,int>>s; s.push(map<string,int>()); int n = formula.size(); for(int i=0;i<n;){ if(formula[i]=='('){ // 遇到左括号新增一个字典 map<string,int>tmp; s.push(tmp); ++i; } else if(formula[i]>='A'&&formula[i]<='Z'){ string t = ""; // 记录元素名 t += formula[i++]; while(i<n&&(formula[i]>='a'&&formula[i]<='z')) t+=formula[i++]; // 记录后面跟着的出现次数 int cnt = 0; while(i<n&&(formula[i]>='0'&&formula[i]<='9')) cnt = cnt*10 + (formula[i++]-'0'); // 填到当前字典中 s.top()[t] += (cnt ? cnt : 1); } // 若是右括号,就把顶层字典弹出,将其中的信息汇总到次顶层字典中 else if(formula[i]==')'){ int cnt = 0; i++; while(i<n&&(formula[i]>='0'&&formula[i]<='9')) cnt = cnt*10 + (formula[i++]-'0'); map<string,int>mp = s.top(); s.pop(); for(auto t:mp){ s.top()[t.first] += (t.second*cnt); } } } // 整个串处理完毕后 最终栈中只有一个字典 return s; } };
题目二:
思路1:迭代
class Solution { public: string decodeString(string s) { if(s.empty()) return ""; vector<int>cnt; vector<char>v; int num = 0; for(int i=0;i<s.size();++i) { // 字符的类型 // 数字 if(s[i]>='0'&&s[i]<='9') { num = num*10 + (s[i]-'0'); } // 左括号 else if(s[i]=='[') { v.push_back('['); cnt.push_back(num); num = 0; } // 右括号 else if(s[i]==']'){ string t = ""; // 出栈直到遇见左括号 while(v.back()!='[') { char x = v.back(); t = x+t; v.pop_back(); } v.pop_back(); // 这段字符要重复的次数 int n = cnt.back(); cnt.pop_back(); while(n--) { for(auto a:t) v.push_back(a); } } // 字母 else{ v.push_back(s[i]); } } string ans = ""; for(auto a:v) ans+=a; return ans; } };
思路2:递归。难点在于递归结束的返回值设计。
class Solution { public: string decodeString(string s) { string res = ""; dfs(s,res,0); return res; } int dfs(string s,string& ans,int i){ int num = 0; while(i<s.size()){ if(isdigit(s[i])) num = num*10 + (s[i] - '0'); else if(s[i]=='['){ // 遇到'[',递归 // 返回解码好的子串和']'位置的索引 递归设计的难点 string tmp = ""; int p = dfs(s,tmp,i+1); while(num>0){ ans+=tmp; num--; } i = p; } else if(s[i]==']') break; else ans+=s[i]; ++i; } return i; } };
题目三
思路1:递归
class Solution { public: int scoreOfParentheses(string s) { int pos = 0; int score = dfs(s,pos); return score; } int dfs(string s,int& i){ int ans = 0; while(i<s.size()){ // 遇到左括号递归计算子串的分数 // 返回分数和处理完的')'的下标 if(s[i]=='('){ int tmp = 0; i++; tmp = dfs(s,i); ans+=tmp; } else{ ans = ans==0 ? 1 : ans*2; break; } ++i; } return ans; } };
思路2:利用栈,迭代。
class Solution { public: int scoreOfParentheses(string str) { int val = 0; // vector保存平衡括号子串的分数 stack<vector<int>>s; // 加一层最外边的括号 方便处理 s.push(vector<int>()); for(int i=0;i<str.size();++i){ // 遇到左括号 新增一个vector来记录子串分数 if(str[i]=='('){ s.push(vector<int>()); } // 遇到右括号 弹出栈顶vector // 将计算好的子串分数汇总到次栈顶的vector中 else{ vector<int>tmp = s.top(); s.pop(); if(tmp.empty()) s.top().push_back(1); else{ int sum = 0; for(auto t:tmp) sum+=t; s.top().push_back(sum*2); } } } // 处理完毕后 只剩下最初新增在最外层的vector // 统计分数和即可 vector<int>ans = s.top(); for(auto a:ans) val+=a; return val; } };