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)

大家都在看

  • WEB自动化-07-Cypress Test Runner

    7 Test Runner 7.1 概述 Test Runner是Cypress非常重要一个组件,其主要作用为运行测试、更改配置、将运行的测试结果写入控制台等等。 打开Cypres…

    Linux 2023年6月7日
    080
  • DHCP服务

    一、dhcp介绍 dhcp 应用层协议 动态主机配置协议 作用: 为主机动态分配tcp/ip参数(ip地址、掩码、网关、DNS服务器地址) Linux实现dhcp服务 软件: dh…

    Linux 2023年6月7日
    070
  • 2021年3月-第01阶段-Linux基础-Linux系统概念-Linux命令

    Linux系统基本概念 图形界面: Ctrl+Shift +号 //调整命令终端变大 Ctrl – 号 //调整命令终端变小 命令终端: ~ 家目录:用户的私有场所,其…

    Linux 2023年6月8日
    090
  • LeetCode 416.分割等和子集 | 类0-1背包问题 | 解题思路及代码

    Given a nonempty array nums, which only contains positive number. Find if the array can be…

    Linux 2023年6月13日
    074
  • 【小记】Ubuntu 工具链升级 gcc 流程

    我的是 Ubuntu Server 20.04 LTS,默认 gcc-9,工具链升级至 gcc-11,和 Ubuntu 22.04 LTS 保持一致。 如果本文发文时间比较旧,你所…

    Linux 2023年6月13日
    066
  • Linux 配置Java环境变量

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 注:目前,您需要在官网下载时登录。在此共享帐户以方便下载。 [En] Note: at present, you …

    Linux 2023年5月27日
    091
  • 网易互联网笔试(3.27)

    网易互联网3.27日笔试,四道笔试题一道简答题,四道笔试题AK,简答题考察设计模式不会。 第一道题模拟使用单体技能和群体技能攻击怪物的场景、第二题字符串处理、第三题构造具有限制条件…

    Linux 2023年6月13日
    095
  • [编译] 9、在Linux下搭建 nordic 最新基于 zephyr 的开发烧写环境

    前言 1、概述 2、安装工具 3、获取 nRF Connect SDK 源码 4、安装 Python modules 5、安装 toolchain 6、下载 nRF Command…

    Linux 2023年6月8日
    072
  • String为什么不是基本数据类型

    java虚拟机处理基础类型与引用类型的方式是不一样的,对于基本类型,java虚拟机会为其分配数据类型实际占用的内存空间,对于引用类型变量,他仅仅是一个指向堆区中某个实例的指针。 O…

    Linux 2023年6月7日
    089
  • aspx.designer.cs没有自动生成代码(没有自动注册)

    遇到这个问题的最大可能是:aspx页面存在bug。 比如说我的主页是从项目里的别的页面复制过来的,但是少复制了一些引用,页面就存在bug,导致aspx.designer.cs没有自…

    Linux 2023年6月7日
    081
  • C语言001–hello world编译详解

    1.编写hello.c程序,并编译运行 book@100ask:~/linux/c01$ cat hello.c -n 1 #include <stdio.h> 2 3…

    Linux 2023年6月6日
    095
  • 每天一个 HTTP 状态码 前言

    HTTP 状态码由 3 位阿拉伯数字构成,其中第一位用于定义 HTTP 响应的类型… 前前言 在重新开始写博文(其实大多也就最多算是日常笔记小结)之际,就想着从短小精悍…

    Linux 2023年6月7日
    087
  • uWSGI服务实现优雅重启(graceful reload)的方式

    服务端当前使用方式 直接通过svc发送SIGINT/SIGKILL信号 直接触发real_run脚本中的相关信号通知 使用简单 每次重启所有进程(包括master),重启完成为全新…

    Linux 2023年6月6日
    091
  • Putty&Psftp命令行实现自动登录

    | 0.18分钟 | 292.8字符 | 1、引言&背景 2、解决方案 3、声明与参考资料 | SCscHero | 2022/1/22 PM6:0 | 系列 | 已完成 …

    Linux 2023年5月27日
    087
  • Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件。 磁盘分区 生磁盘可以被分区,分区…

    Linux 2023年5月27日
    084
  • http代理连接

    基于Linux服务器的http代理连接 1. 准备工作 &#x76EE;&#x6807;&#x670D;&#x52A1;&#x5668; &…

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