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操作系统原理

    虽然计算机相关专业,操作系统和计算机组成原理是必修课。但是大学时和真正从事相关专业工作之后,对于知识的认知自然会发生变化。还很有可能,一辈子呆在学校的老师们只是照本宣科,自己的理解…

    Linux 2023年6月14日
    093
  • 一文入门Qt Quick

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」 https://mp.weixin.qq.com/s/dvamU6q5lZQb5hztfD2zNg 初识…

    Linux 2023年6月6日
    0122
  • SQL查询语句–统计

    — 1、日统计查询填补 i->为时间差的天数 2022-05-10为终止时间 SET @i :=- 1; SELECT date_format( DATE_SUB( ’20…

    Linux 2023年6月14日
    085
  • 从前端走向后端

    每次过年回老家聚会,遇到不熟悉的亲戚朋友,经常被问到职业是什么。一开始,我总是很认真的回答这个问题,结果常常引出一番尴尬的问答。 &#x201C;&#x4F60;&…

    Linux 2023年6月6日
    0101
  • 阅读习惯2(选做)

    任务详情 参考https://www.cnblogs.com/rocedu/p/6528920.html 提交微信读书(或其他平台)目前的读书数据(总时长,册数,笔记数等)的截图,…

    Linux 2023年6月8日
    0100
  • MIT6.828——Lab1 partA(麻省理工操作系统课程实验)

    Lab1 基本部分 在实验给出的文档中,已经详说明了早期PC的内存布局,并且运行了 bootloader。详细地解释了,上电后BIOS所做的工作,因此这部分不再赘述。需要注意的是 …

    Linux 2023年5月27日
    0176
  • 016 Linux 卧槽,看懂进程信息也不难嘛?top、ps

    1 扒开看看 top 命令参数详情 第一行,[top – ]任务队列信息 第二行,[Tasks] 任务(进程) 第三行,[Cpu(s)]状态信息 第四行,[Mem]内存…

    Linux 2023年5月27日
    0122
  • 利用 C# 给 Windows 资源管理器注册右键菜单(Windows Shell)(一):入门

    前言 关于 SharpShell SharpShell makes it easy to create Windows Shell Extensions using the .NE…

    Linux 2023年5月28日
    089
  • Linux 如何设置开机自启动脚本

    https://blog.csdn.net/weixin_40343504/article/details/82457990 Original: https://www.cnblo…

    Linux 2023年6月13日
    0105
  • redis变慢查询

    Redis 通常是我们业务系统中一个重要的组件,比如:缓存、账号登录信息、排行榜等。 一旦 Redis 请求延迟增加,可能就会导致业务系统”雪崩”。 我在单…

    Linux 2023年5月28日
    0100
  • 不割韭菜,纯分享:剖析HTML中的类,运维开发必备前端技能,我们一起坚持。

    写在开篇 开篇之前,先提个问题,什么是类?分类吗?可以这么说吧!我们可以给物体分类,也可以给人分类。正所谓,物以类聚,人以群分。难道我们这里是给元素分类?用分类来理解是不准确的啦!…

    Linux 2023年6月7日
    0106
  • linux命令之tar 解压 压缩

    tar(全称:tape archive )命令用于备份文件。tar 是用来 创建或者 还原备份文件的工具程序,它可以加入,解开备份文件内的文件。tar linux说明 tar [&…

    Linux 2023年5月27日
    082
  • 线程池如何保证核心线程一直存活

    转载请注明出处: 查看 ThreadPoolExecutor 类中的 getTask 方法,这个方法可以保持核心线程在没有任务的时候也可以一直处于存活状态 核心在于 workQue…

    Linux 2023年6月14日
    0158
  • Shell脚本生成密码

    利用 /dev/urando 生成密码 密码以字母、数字、开头 特殊符号多 for _ in {1..30};do tr -dc ‘~`!@#$%^&*()_+-={}:&…

    Linux 2023年6月6日
    0112
  • 操作系统实战45讲笔记-01 程序的运行过程:从代码到机器运行

    计算机硬件是无法直接运行C 语言文本程序代码的,需要 C 语言编译器,把这个代码编译成具体硬件平台的二进制代码。再由具体操作系统建立进程,把这个二进制文件装进其进程的内存空间中,才…

    Linux 2023年6月7日
    091
  • djnago-filter用法

    django-filter用法 集成drf 不指定字段的过滤参数,那么该字段就默认为exact,精准匹配自定义filter文件内 from django_filters impor…

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