Number of Atoms Leetcode #726 题解[C++]

题目来源


https://leetcode.com/problems/number-of-atoms/description/

题意分析


Given a chemical formula (given as a string), return the count of each atom.

An atomic element always starts with an uppercase character, then zero or more lowercase letters, representing the name.

1 or more digits representing the count of that element may follow if the count is greater than 1. If the count is 1, no digits will follow. For example, H2O and H2O2 are possible, but H1O2 is impossible.

Two formulas concatenated together produce another formula. For example, H2O2He3Mg4 is also a formula.

A formula placed in parentheses, and a count (optionally added) is also a formula. For example, (H2O2) and (H2O2)3 are formulas.

Given a formula, output the count of all elements as a string in the following form: the first name (in sorted order), followed by its count (if that count is more than 1), followed by the second name (in sorted order), followed by its count (if that count is more than 1), and so on.

Example 1:

Input:
formula = “H2O”
Output: “H2O”
Explanation:
The count of elements are {‘H’: 2, ‘O’: 1}.

Example 2:

Input:
formula = “Mg(OH)2”
Output: “H2MgO2”
Explanation:
The count of elements are {‘H’: 2, ‘Mg’: 1, ‘O’: 2}.

Example 3:

Input:
formula = “K4(ON(SO3)2)2”
Output: “K4N2O14S4”
Explanation:
The count of elements are {‘K’: 4, ‘N’: 2, ‘O’: 14, ‘S’: 4}.

Note:

All atom names consist of lowercase letters, except for the first character which is uppercase.
The length of formula will be in the range [1, 1000].
formula will only consist of letters, digits, and round parentheses, and is a valid formula as defined in the problem.

给出一个化学式, 数出每种原子的原子数.

解题思路


就是一个字符串处理, 也就有了这类题的一贯特点—–坑. 逻辑好像简单, 就是那么回事, 一旦写起代码来各种恶心越界访问, 逻辑问题.

在说这道题之前, 博主相信大多数人都有写过那个著名的括号匹配问题, 当时的思路是利用栈来处理括号.

因为像 M g ( O H ) 2 这样的化学式难免有括号, 所以我们也可以采取类似的方法来解决处理. 这里我们不能用栈了, 因为我们还要完成统计原子数的任务, 不能这么快就把原子弹出去.

首先, 我们需要先构思好完整无误的读取原子(足以处理 Mg&或 K$这样的), 读取数字, 读取括号的代码, 这部分便不展开. 博主的思路是构建两个vector, 一个用来保存原子, 另一个用来保存原子对应的原子数.

对于原子直接压进原子vector, 左括号也直接压进原子vector; 对于数字直接压进计数vector, 但是要注意当原子数为 1 时也要记得压一个 1 进去计数vector. 而一旦碰到右括号, 则在原子vector中找到和它匹配的第一个左括号, 对于在它们之间的原子, 将它们在计数vector中对应的计数乘以相应的倍数. 最后把左括号删除出vector. 千言万语一张图. 详细请见下图.
ac
上图演示了碰到一次右括号之后两个vector中应该发生的变化.

等到遍历完字符串后, 我们的AtomVector中必然已经没有了左括号, 这时候我们只需要简单的统计各种原子的原子数即可.

代码实现


#include <string>
#include <iostream>
#include <cctype>
#include <stack>
#include <vector>
#include <map>

using namespace std;


class Solution {
public:
    string countOfAtoms(string formula) {
        if (formula.empty()) return string();
        map<string, int> statis;
        vector<string> AtomStack;
        vector<int> AtomCount;
        string singleAtom, singleAtomCount,ret;

        //Traverse the string
        for (int count = 0; count < formula.size();) {
            singleAtom.clear();
            if (isupper(formula[count])) singleAtom = string(1, formula[count]);
            while (true && count < formula.size() && !singleAtom.empty() && islower(formula[++count]))
                    singleAtom.push_back(formula[count]);

            //Count Atom apperance times
            singleAtomCount.clear();
            while (count<formula.size()&&isdigit(formula[count]))
                    singleAtomCount.push_back(formula[count++]);

            //Log
            if (!singleAtom.empty())
            {
                AtomStack.push_back(singleAtom);
                if (singleAtomCount.empty()) AtomCount.push_back(1);
                else AtomCount.push_back(strtol(singleAtomCount.c_str(),nullptr,10));
            }
            else if(!singleAtomCount.empty()) AtomCount.push_back(strtol(singleAtomCount.c_str(), nullptr,10));

            //Special Char
            if (count < formula.size() && formula[count] == '('&&++count) {
                AtomStack.push_back("(");
            }
            //Deal a pair of parenthesis
            else if(count < formula.size() && formula[count] == ')'){
                singleAtomCount.clear();
                while (++count<formula.size() && isdigit(formula[count]))
                    singleAtomCount.push_back(formula[count]);
                //The _sub of (*)
                int times = strtol(singleAtomCount.c_str(), nullptr,10);
                int i, j = AtomCount.size() - 1;
                for (i = AtomStack.size()-1; AtomStack[i] != "("; i--) {
                    AtomCount[j--] *= times;
                }
                //Erase '('
                AtomStack.erase(AtomStack.begin() + i);
            }

        }

        //Empty those remain in stack
        while (!AtomStack.empty()) {
            singleAtom = AtomStack.back();
            if (statis.count(singleAtom)) statis[singleAtom] += AtomCount.back();
            else statis[singleAtom] = AtomCount.back();
            AtomStack.pop_back();
            AtomCount.pop_back();
        }

        //Calculate the result
        for (auto it = statis.begin(); it != statis.end(); it++) {
            ret += it->first;
            if (it->second != 1) ret += to_string(it->second);
        }

        return ret;
    }
};

代码表现


港真, 这类题A了之后还是相当开心的说. (づ ̄3 ̄)づ╭❤~
(小猪佩奇身上纹, 掌声送给社会人. \手动滑稽)
726_ac

猜你喜欢

转载自blog.csdn.net/wayne_mai/article/details/80291104