LWC 58:726. Number of Atoms

LWC 58:726. Number of Atoms

传送门:726. Number of Atoms

Problem:

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.

思路: 递归真的是个好东西,思路比较暴力,如果没有遇到括号,则按照传统的检测字符和数字进行更新即可。如果检测到括号,则先得到括号内的元素和个数的映射,接着乘上大括号外的第一个num,再将第三部分的答案组合进来即可。

比如:

H2O2(SO2)23(OH)23

上述字符串可以组成三部分

lf = "H2O2"
mid = "(SO2)23" 
rt = "(OH)23"

只有mid需要特殊处理,把{s = 1 * 32, O = 2 * 23 = 46}
而一旦解决mid,则rt跟着被解决,lf在之前就被解决了,具体看代码,不解释了。

代码如下:

    public String countOfAtoms(String formula) {
        Map<String, Integer> map = go(formula.toCharArray(), 0, formula.length() - 1);

        StringBuilder sb = new StringBuilder();
        List<String> set = new ArrayList<>(map.keySet());
        Collections.sort(set);
        for (String key : set) {
            sb.append(key);
            if (map.get(key) > 1) {
                sb.append(map.get(key));
            }
        }
        return sb.toString();
    }

    public Map<String, Integer> go(char[] cs, int s, int e){
        if (s > e) return new HashMap<>();

        Map<String, Integer> ans = new HashMap<>();
        int idx = new String(cs).substring(s, e + 1).indexOf("(");
        if (idx != -1) idx += s;
        if (idx == -1) {

            StringBuilder sb = new StringBuilder();
            for (int i = s; i <= e;) {
                if (Character.isUpperCase(cs[i])) {
                    sb.append(cs[i]);
                    i ++;

                    if (i <= e && Character.isUpperCase(cs[i])) {
                        String ele = sb.toString();
                        if (!ans.containsKey(ele)) {
                            ans.put(ele, 1);
                        }
                        else {
                            ans.put(ele, ans.get(ele) + 1);
                        }
                        sb = new StringBuilder();
                    }
                    else if (i <= e && Character.isLowerCase(cs[i])) {
                        while (i <= e && Character.isLowerCase(cs[i])) {
                            sb.append(cs[i]);
                            i ++;
                        }
                        if (i <= e && !Character.isDigit(cs[i])){
                            String ele = sb.toString();
                            if (!ans.containsKey(ele)) {
                                ans.put(ele, 1);
                            }
                            else {
                                ans.put(ele, ans.get(ele) + 1);
                            }
                            sb = new StringBuilder();
                        }
                    }

                    if (i <= e && Character.isDigit(cs[i])) {
                        int num = 0;
                        while (i <= e && Character.isDigit(cs[i])) {
                            num = num * 10 + cs[i] - '0';
                            i ++;
                        }

                        String ele = sb.toString();
                        if (!ans.containsKey(ele)) {
                            ans.put(ele, num);
                        }
                        else {
                            ans.put(ele, ans.get(ele) + num);
                        }

                        sb = new StringBuilder();
                    }
                }
            }

            String ele = sb.toString();
            if (!ele.isEmpty()) {
                if (!ans.containsKey(ele)) {
                    ans.put(ele, 1);
                }
                else {
                    ans.put(ele, ans.get(ele) + 1);
                }
            }
            return ans;
        }
        else {
            Map<String, Integer> lf = go(cs, s, idx - 1);

            StringBuilder sb = new StringBuilder();
            int p = 1;
            Map<String, Integer> include;
            int num = 0;
            int j = -1;
            for (int i = idx + 1; i <= e; ++i) {
                sb.append(cs[i]);
                if (cs[i] == '(') {
                    p ++;
                }
                else if (cs[i] == ')') {
                    p --;
                    if (p == 0) {
                        j = i + 1;
                        while (j <= e && Character.isDigit(cs[j])) {
                            num = num * 10 + cs[j] - '0';
                            j ++;
                        }
                        break;
                    }
                }
            }
            String ele = sb.toString().substring(0, sb.length() - 1);
            include = go(ele.toCharArray(), 0, ele.length() - 1);

            for (String key : include.keySet()) {
                include.put(key, include.get(key) * num);
            }

            Map<String, Integer> rt = go(cs, j, e);

            add(ans, lf);
            add(ans, include);
            add(ans, rt);

            return ans;
        }
    }

    public void add(Map<String, Integer> ans, Map<String, Integer> tmp) {
        for (String key : tmp.keySet()) {
            if (!ans.containsKey(key)) {
                ans.put(key, tmp.get(key));
            }
            else {
                ans.put(key, ans.get(key) + tmp.get(key));
            }
        }
    }

注意一些细节: 首先,对于字符串”H2O2BeBe49”这样的formula,第一次一定会遇到大写字符,接着把大写字母后的小写字母全部给append上,这样只会遇到两种情况:下一个字符为数字,或者下一个字符为大写字符。

如过遇到字符,则计算num,如果遇到大写字符,则formula省略了1,需要加上。

代码更新如下:

    public String countOfAtoms(String formula) {
        Map<String, Integer> map = go(formula.toCharArray(), 0, formula.length() - 1);

        StringBuilder sb = new StringBuilder();
        List<String> set = new ArrayList<>(map.keySet());
        Collections.sort(set);
        for (String key : set) {
            sb.append(key);
            if (map.get(key) > 1) {
                sb.append(map.get(key));
            }
        }
        return sb.toString();
    }

    public Map<String, Integer> go(char[] cs, int s, int e){
        if (s > e) return new HashMap<>();

        Map<String, Integer> ans = new HashMap<>();
        int idx = new String(cs).substring(s, e + 1).indexOf("(");
        if (idx != -1) idx += s;
        if (idx == -1) {

            StringBuilder sb = new StringBuilder();
            for (int i = s; i <= e;) {
                if (Character.isUpperCase(cs[i])) {
                    sb.append(cs[i]);
                    i ++;

                    while (i <= e && Character.isLowerCase(cs[i])){
                        sb.append(cs[i]);
                        i ++;
                    }

                    if (i <= e && !Character.isDigit(cs[i])){
                        String ele = sb.toString();
                        if (!ans.containsKey(ele)) {
                            ans.put(ele, 1);
                        }
                        else {
                            ans.put(ele, ans.get(ele) + 1);
                        }
                        sb = new StringBuilder();
                    }
                    else if (i <= e && Character.isDigit(cs[i])) {

                        int num = 0;
                        while (i <= e && Character.isDigit(cs[i])) {
                            num = num * 10 + cs[i] - '0';
                            i ++;
                        }

                        String ele = sb.toString();
                        if (!ans.containsKey(ele)) {
                            ans.put(ele, num);
                        }
                        else {
                            ans.put(ele, ans.get(ele) + num);
                        }

                        sb = new StringBuilder();
                    }
                }
            }

            String ele = sb.toString();
            if (!ele.isEmpty()) {
                if (!ans.containsKey(ele)) {
                    ans.put(ele, 1);
                }
                else {
                    ans.put(ele, ans.get(ele) + 1);
                }
            }
            return ans;
        }
        else {
            Map<String, Integer> lf = go(cs, s, idx - 1);

            StringBuilder sb = new StringBuilder();
            int p = 1;
            Map<String, Integer> include;
            int num = 0;
            int j = -1;
            for (int i = idx + 1; i <= e; ++i) {
                sb.append(cs[i]);
                if (cs[i] == '(') {
                    p ++;
                }
                else if (cs[i] == ')') {
                    p --;
                    if (p == 0) {
                        j = i + 1;
                        while (j <= e && Character.isDigit(cs[j])) {
                            num = num * 10 + cs[j] - '0';
                            j ++;
                        }
                        break;
                    }
                }
            }
            String ele = sb.toString().substring(0, sb.length() - 1);
            include = go(ele.toCharArray(), 0, ele.length() - 1);

            for (String key : include.keySet()) {
                include.put(key, include.get(key) * num);
            }

            Map<String, Integer> rt = go(cs, j, e);
            add(ans, lf);
            add(ans, include);
            add(ans, rt);

            return ans;
        }
    }

    public void add(Map<String, Integer> ans, Map<String, Integer> tmp) {
        for (String key : tmp.keySet()) {
            if (!ans.containsKey(key)) {
                ans.put(key, tmp.get(key));
            }
            else {
                ans.put(key, ans.get(key) + tmp.get(key));
            }
        }
    }     

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LinkedBear的个人空间

唠唠SE的集合-02——Iterator迭代器

迭代时如果没有先执行next()则会抛出IllegalStateException,这就意味着必须要先检查是否还有下一个可以被迭代的元素,才能往外取。

1033
来自专栏java学习

Java每日一练(2017/8/17)

每日一句 学的到东西的事情是锻炼,学不到的是磨练。 查看以前的所有练习题目以及答案:https://mp.weixin.qq.com/mp/homepage?_...

2929
来自专栏十月梦想

Map数据结构以及方法和数据遍历

    前面说过Set和Map是ES6中的新的数据结构(不是数据类型是存储数据的集合结构),上面说过,Set类似与数据的形式而这个类似与object(对象),看...

3013
来自专栏郭耀华‘s Blog

剑指offer第五天

28.数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2...

2755
来自专栏java一日一条

Java面试题:如何对HashMap按键值排序

Java中HashMap是一种用于存储“键”和“值”信息对的数据结构。不同于Array、ArrayList和LinkedLists,它不会维持插入元素的顺序。

1142
来自专栏编程

Python基础1

数据类型 Python3中有6钟标准的数据类型:Number(数字)、String(字符 串)、List(列表)、Tuple(元组)、Sets(集合)、Dict...

22810
来自专栏闻道于事

Java之集合初探(一)

一、集合概述、区别 集合是一种容器,数组也是一种容器 在Java编程中,装各种各样的对象(引用类型)的叫做容器。 为什么出现集合类? 面向对象语言对事物的体现都...

2557
来自专栏Ryan Miao

java中List对象列表去重或取出以及排序

面试碰到几次list的去重和排序。下面介绍一种做法: 1. list去重 1.1 实体类Student List<Student>容量10k以上,要求去重复。这...

7939
来自专栏Bingo的深度学习杂货店

Q7 Reverse Integer

Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 1...

2964
来自专栏一个会写诗的程序员的博客

第7章 集合类第7章 集合类

在 Java 类库中有一套相当完整的容器集合类来持有对象。Kotlin没有去重复造轮子(Scala则是自己实现了一套集合类框架),而是在Java 类库的基础上进...

812

扫码关注云+社区

领取腾讯云代金券