1. 程式人生 > >LeetCode 726. Number of Atoms

LeetCode 726. Number of Atoms

題意:給出一個化合物的化學式 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;
}