LeetCode 726: 原子的数量-栈和Map的结合以及字符串处理 | Number of Atoms-Combination of stack, map and string processing

Problem Description

Give a chemical formula, return the count of each atom.

  • The count after atom only writes if it’s more than 1
  • A formula placed in parentheses, and a count after the right parenthesis(maybe not) is also a formula: (H2O2), (H2O)2
  • The atom in the returned string should in lexicographic order

Example:

Input: formula = "Mg(OH)2"
Output: "H2MgO2"

Problem Analysis

It is obvious that the difficulty in this problem is to remove the parentheses.

Each atom inside a parentheses, needs to multiple the count outside the parentheses. Because the number of atoms in this parentheses needs to be multipled by, and each atom has its corresponding count. So we can abstract the content inside each parentheses as a map.

So an outer parentheses may contains may inner parentheses inside: (Fe2(SO4)3)2, so we can regard the inner parentheses part SO4 as a innerMap, the outer Fe2(innerMap)3 as the outer map.

We can go through from left to right

  • If comes a (, then we create a new inner map
  • If comes an atom, then we record its number in the inner map
  • If comes a ), then we open the inner map, multiple each atom number with the number comes after )(if no number following, just multiple 1). And finally, merge the multipled inner map to the outer map.

And the outer map multipled and merge to the outer’s outer map, and etc.

So we can use a stack whose elements are maps to solve this problem.

String formula;
int idx, len;

public String countOfAtoms(String fml) {
    this.formula = fml; // the chemical formula
    this.idx = 0; // the index we are handling
    this.len = formula.length();
    // create the map stack
    Deque> stack = new ArrayDeque<>();
    // default map containing atoms outside any parentheses, eg:Fe in Fe2(SO4)3
    stack.push(new HashMap());
    while (idx < len) {
        switch (formula.charAt(idx)) {
            case '(':
                // create a new inner map to hold atoms inside the parenthese
                stack.push(new HashMap());
                idx++;
                break;
            case ')':
                idx++;
                Map innerMap = stack.pop();
                Map outerMap = stack.peek();
                int cnt = nextNum();
                // multiple the inner cnt with the )n's n, and join to the outerMap
                for (String s : innerMap.keySet()) {
                    outerMap.put(s, outerMap.getOrDefault(s, 0) + innerMap.get(s) * cnt);
                }
                break;
            default:
                // atom
                // record this atom's number
                Map map = stack.peek();
                String atom = nextAtom();
                int n = nextNum();
                map.put(atom, map.getOrDefault(atom, 0) + n);
        }
    }
    // turn outest map to a treeMap so that the atom name is ordered
    TreeMap treeMap = new TreeMap<>(stack.peek());
    StringBuilder sb = new StringBuilder();
    for (String s : treeMap.keySet()) {
        sb.append(s);
        int cnt = treeMap.get(s);
        if (cnt > 1) {
            sb.append(String.valueOf(cnt));
        }
    }
    return sb.toString();
}

Meanwhile, we need to handle each atom’s name and next number. Java support useful functions to easily reach the goal:

private String nextAtom() {
    int start = idx++;
    // continue matching while next character is a lowercase character
    while (idx < len && Character.isLowerCase(formula.charAt(idx))) {
        idx++;
    }
    return formula.substring(start, idx);
}
private int nextNum() {
    // If the following is not a number, return the default 1
    if (idx == len || !Character.isDigit(formula.charAt(idx))) {
        return 1;
    }
    int start = idx++;
    // continue matching while next character is a digit
    while (idx < len && Character.isDigit(formula.charAt(idx))) {
        idx++;
    }
    return Integer.parseInt(formula.substring(start, idx));
}

Complete code:

class Solution{
    String formula;
    int idx, len;

    public String countOfAtoms(String fml) {
        this.formula = fml; // the chemical formula
        this.idx = 0; // the index we are handling
        this.len = formula.length();
        // create the map stack
        Deque> stack = new ArrayDeque<>();
        // default map containing atoms outside any parentheses, eg:Fe in Fe2(SO4)3
        stack.push(new HashMap());
        while (idx < len) {
            switch (formula.charAt(idx)) {
                case '(':
                    // create a new inner map to hold atoms inside the parenthese
                    stack.push(new HashMap());
                    idx++;
                    break;
                case ')':
                    idx++;
                    Map innerMap = stack.pop();
                    Map outerMap = stack.peek();
                    int cnt = nextNum();
                    // multiple the inner cnt with the )n's n, and join to the outerMap
                    for (String s : innerMap.keySet()) {
                        outerMap.put(s, outerMap.getOrDefault(s, 0) + innerMap.get(s) * cnt);
                    }
                    break;
                default:
                    // atom
                    // record this atom's number
                    Map map = stack.peek();
                    String atom = nextAtom();
                    int n = nextNum();
                    map.put(atom, map.getOrDefault(atom, 0) + n);
            }
        }
        // turn outest map to a treeMap so that the atom name is ordered
        TreeMap treeMap = new TreeMap<>(stack.peek());
        StringBuilder sb = new StringBuilder();
        for (String s : treeMap.keySet()) {
            sb.append(s);
            int cnt = treeMap.get(s);
            if (cnt > 1) {
                sb.append(String.valueOf(cnt));
            }
        }
        return sb.toString();
    }

    private String nextAtom() {
        int start = idx++;
        // continue matching while next character is a lowercase character
        while (idx < len && Character.isLowerCase(formula.charAt(idx))) {
            idx++;
        }
        return formula.substring(start, idx);
    }

    private int nextNum() {
        // If the following is not a number, return the default 1
        if (idx == len || !Character.isDigit(formula.charAt(idx))) {
            return 1;
        }
        int start = idx++;
        // continue matching while next character is a digit
        while (idx < len && Character.isDigit(formula.charAt(idx))) {
            idx++;
        }
        return Integer.parseInt(formula.substring(start, idx));
    }
}

Original: https://www.cnblogs.com/liuzhch1/p/16413887.html
Author: liuzhch1
Title: LeetCode 726: 原子的数量-栈和Map的结合以及字符串处理 | Number of Atoms-Combination of stack, map and string processing

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606688/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【原创】Linux中断子系统(三)-softirq和tasklet

    背景 Read the fucking source code! –By 鲁迅 A picture is worth a thousand words. –…

    Linux 2023年6月8日
    0102
  • Java50个关键字之static

    关键字static主要有两种作用:第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关。第二,希望某个方法或属性与类而不是对象关联在一起,也就是说,在不创建对象的…

    Linux 2023年6月7日
    098
  • Linux at命令详解

    大家好,我是良许。 在生活中,我们有太多的场景需要使用闹钟,比如早上7点起床,下午4点开会,晚上8点购物,等等。 [En] In life, we have too many sc…

    Linux 2023年5月27日
    0110
  • 分布式计算的本质、特点和未来

    在计算机早期,都是由一台主机承担全部存储和计算工作,这种方式被称为集中处理。后来随着处理器发展和网络出现,衍生出客户机/服务器架构,即由服务器完成主要的存储计算工作,客户机则负责较…

    Linux 2023年6月6日
    0116
  • angular报错:Cannot assign to a reference or variable

    错误代码: <input #manufacturerId="ngModel" id="manufacturerId" name=&qu…

    Linux 2023年6月7日
    0101
  • python写一个双色球彩票计算器

    首先声明,赌博一定不是什么好事,也完全没有意义,不要指望用彩票发财。之所以写这个,其实是用来练手的,可以参考这个来预测一些其他的东西,意在抛砖引玉。 啰嗦完了,马上开始,先上伪代码…

    Linux 2023年6月6日
    0106
  • Identity Server 4客户端认证控制访问API(一)

    一、说明 我们将定义一个api和要访问它的客户端,客户端将在identityser上请求访问令牌,并使用访问令牌调用api 二、项目结构与准备 1、创建项目QuickStartId…

    Linux 2023年6月13日
    098
  • [Linux]iptables防火墙

    一、iptables介绍 二、表(Table) 三、链(Chain) 四、规则(Rule) 五、iptables规则的增删改查 一、iptables介绍 iptables是一个针对…

    Linux 2023年6月13日
    0110
  • Linux Centos 打开和关闭防火墙

    systemctl status firewalld.service # 查看防火墙状态 systemctl start firewalld.service # 开启防火墙 sys…

    Linux 2023年6月13日
    0114
  • 面试题:Java中为什么只有值传递?

    作者:小牛呼噜噜 | https://xiaoniuhululu.com计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 经典的问题 形参&实参…

    Linux 2023年6月6日
    0133
  • 错误域控降级导致解析问题

    近两天在给分部安装辅助域控的时候,总是安装不成功,或者安装时成功了但是无法复制主域或者其他域控的信息,同步失败,还有就是它一直没有网。 解决方案 经过排查发现域名dns解析不对,经…

    Linux 2023年6月8日
    0117
  • redis出现错误:NOAUTH Authentication required.

    出现认证问题,应该是设置了认证密码,输入密码既可以啦 注意密码是字符串形式! 127.0.0.1:6379> auth "yourpassword" 密码…

    Linux 2023年5月28日
    084
  • identity server4 授权成功页面跳转时遇到错误:Exception: Correlation failed. Unknown location的解决方法

    一、异常信息描述 错误信息,看到这个页面是否耳熟能详担又不知道怎么解决 ,坑死个人不偿命,,,,,,,, 二、处理方法 1、在web项目中增加类SameSiteCookiesSer…

    Linux 2023年6月13日
    0124
  • 初学ajax

    ajax出现无疑改变了web应用:从开始的整体页面的刷新到局部页面的数据显示,不用刷新页面就可以与服务器交互; 1 function ajaxPost(data){ 2 3 var…

    Linux 2023年6月14日
    087
  • linux 普通分区与lvm分区

    安装linux系统时 有时候会提示lvm分区与标准分区 首先普及一下lvm分区:lvm是 logical volume manager (逻辑卷管理),linux环境下对磁盘分区的…

    Linux 2023年6月14日
    097
  • 基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)

    vite 最近非常火,它是 vue 作者尤大神发布前端构建工具,底层基于 Rollup,无论是启动速度还是热加载速度都非常快。vite 随 vue3 正式版一起发布,刚开始的时候与…

    Linux 2023年6月7日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球