LeetCode 726. Number of Atoms
阿新 • • 發佈:2018-11-09
題意:給出一個化合物的化學式 eg, Mg(OH)2 and K4(ON(SO3)2)2,統計出其每個原子的個數
很明顯用遞迴做,如果遇到a(bcd)ef,則bcd構成一個子問題,遞迴處理統計出各個原子出現的頻率(用map記錄),如果e是個數字,返回後merge頻率乘上該數字即可。
但是需要保證先處理外面的括號,再處理內部的括號e.g., (a(bdc)e)。我把一塊當做merge inteval處理了,但感覺沒必要,因為不會出現([)]的情況。用棧可以得出所有括號匹配的區間,merge interval之後得到的區間都是最外層的。e.g., (ab)c(de), a(bc[內部的括號在子問題中再處理]d)e。
另外統計括號外部的原子頻率時,需要跳過括號內部的部分。可以Maintain一個cnt,遇到區間左端點+1,遇到區間右端點-1,cnt=0則表示區間之外。
wa了幾次都是merge interval最初或者最後忘記記錄interval了。另外數字可能不是一位數。
複雜度是N^2,因為每個字母只會訪問一次,處理(abc)之後如果原先的(abc)d中d是數字,則需要O(N)去計算merge之後的頻率。
#include<iostream> #include<stdio.h> #include<cstdio> #include<string> #include<cmath> #include<stdlib.h> #include<algorithm> #include<string.h> #include<cstring> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> #include<stack> using namespace std; //leetcode 726. Number of Atoms const int maxn=1010; int T; int N; int M; class Solution { public: //save the branket position left is i, right is pos[i] string countOfAtoms(string formula) { cout<<formula<<endl; map<string,int>mp=dfs(0,formula.length(),formula); string ret; for(auto iter=mp.begin();iter!=mp.end();iter++) { ret+=iter->first; if(iter->second!=1) { int tmp=iter->second; string s=""; while(tmp!=0) { s+=(tmp%10)+'0'; tmp/=10; } reverse(s.begin(),s.end()); ret+=s; } cout<<iter->first<<" "<<iter->second<<endl; } return ret; } map<string,int> dfs(int st,int ed,string formula) { // cout<<st<<" start dfs "<<ed<<endl; int pos[maxn]; memset(pos,0,sizeof(pos)); map<string,int>mp; stack<int>sta; vector<pair<int,int> >interval; vector<pair<int,int> >merged_interval; for(int i=st;i<ed;i++) { if(formula[i]=='(') { sta.push(i); } if(formula[i]==')') { int tmp=sta.top(); sta.pop(); interval.push_back(make_pair(tmp,i)); } } if(interval.size()!=0) { sort(interval.begin(),interval.end()); int interval_st=interval[0].first; int interval_ed=interval[0].second; pos[interval_st]=1; pos[interval_ed]=-1; for(int i=0;i<interval.size();i++) { // cout<<"interval "<<interval[i].first<<" "<<interval[i].second<<endl; if(interval_ed<interval[i].second) { merged_interval.push_back(make_pair(interval_st,interval_ed)); interval_st=interval[i].first; interval_ed=interval[i].second; pos[interval_st]=1; pos[interval_ed]=-1; } else { interval_ed=max(interval_ed,interval[i].second); } } merged_interval.push_back(make_pair(interval_st,interval_ed)); pos[interval_st]=1; pos[interval_ed]=-1; } // cout<<merged_interval.size()<<endl; for(int i=0;i<merged_interval.size();i++) { // cout<<"merged interval "<<merged_interval[i].first<<" "<<merged_interval[i].second<<endl; map<string,int>mp2=dfs(merged_interval[i].first+1,merged_interval[i].second,formula); int prod=1; int idx=merged_interval[i].second+1; // cout<<formula<<endl; if(idx<formula.length()&&formula[idx]>='0'&&formula[idx]<='9') { int num=0; while(idx<formula.length()&&formula[idx]>='0'&&formula[idx]<='9') { // cout<<idx<<" "<<formula[idx]<<endl; num*=10; num+=formula[idx]-'0'; idx++; } // cout<<num<<endl; prod=num; } for(auto iter=mp2.begin();iter!=mp2.end();iter++) { // cout<<"Add "<<iter->first<<" "<<iter->second<<" "<<prod<<" "<<iter->second*prod<<endl; if(mp.find(iter->first)==mp.end()) { mp[iter->first]=iter->second*prod; } else { mp[iter->first]+=iter->second*prod; } // cout<<"after add in mp "<<mp[iter->first]<<endl; } } int cnt=0; cout<<st<<" "<<ed<<endl; for(int i=st;i<ed;i++) { cnt+=pos[i]; // cout<<i<<" add at end "<<formula[i]<<" "<<pos[i]<<" "<<cnt<<endl; if(cnt==0&&formula[i]>='A'&&formula[i]<='Z') { string tmp=" "; tmp[0]=formula[i]; i++; while(i<formula.length()&&formula[i]>='a'&&formula[i]<='z') { tmp+=formula[i]; i++; } if(i<formula.length()&&formula[i]>='0'&&formula[i]<='9') { int num=0; while(i<formula.length()&&formula[i]>='0'&&formula[i]<='9') { num*=10; num+=formula[i]-'0'; i++; } mp[tmp]+=num; // cout<<tmp<<" add "<<num<<endl; } else { mp[tmp]+=1; // cout<<tmp<<" add 1 "<<endl; } i--; } } // cout<<"return "<<endl; return mp; } }; int main() { freopen("input.txt","r",stdin); cin>>T; for(int ca=1;ca<=T;ca++) { string S; cin>>S; cin.ignore(); Solution sol; cout<<"Case #"<<ca<<": "<<sol.countOfAtoms(S)<<endl; } return 0; }