给定一个化学式formula(作为字符串),返回每种原子的数量。
原子总是以一个大写字母开始,接着跟随0个或任意个小写字母,表示原子的名字。
如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如,H2O 和 H2O2 是可行的,但 H1O2 这个表达是不可行的。
两个化学式连在一起是新的化学式。例如 H2O2He3Mg4 也是化学式。
一个括号中的化学式和数字(可选择性添加)也是化学式。例如 (H2O2) 和 (H2O2)3 是化学式。
给定一个化学式 formula ,返回所有原子的数量。格式为:第一个(按字典序)原子的名字,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-atoms
输入:formula = “H2O”
输出:“H2O”
解释:
原子的数量是 {‘H’: 2, ‘O’: 1}。
import java.util.*;
public class Solution {
class AtomNums{
StringBuffer name;
Integer nums;
public StringBuffer getName() {
return name;
}
public void setName(StringBuffer name) {
this.name = name;
}
public Integer getNums() {
return nums;
}
public void setNums(Integer nums) {
this.nums = nums;
}
@Override
public String toString() {
return "AtomNums{" +
"name=" + name +
", nums=" + nums +
'}';
}
}
public String countOfAtoms(String str){
LinkedList<AtomNums> a=new LinkedList<>();//符号栈
LinkedList<Integer> b=new LinkedList<>();//数字栈
for(int i=str.length()-1;i>=0;i--){
if (str.charAt(i)>='0'&&str.charAt(i)<='9'){ //将数字压入栈中去
int j=i;
int flag=0;
while (str.charAt(j)>='0'&&str.charAt(j)<='9'){
switch (flag){
case 0:
b.addLast((int)str.charAt(j)-48);
break;
case 1:
int temp=b.getLast();
b.removeLast();
b.addLast(((int)str.charAt(j)-48)*10+temp);
break;
case 2:
int temp1=b.getLast();
b.removeLast();
b.addLast(((int)str.charAt(j)-48)*100+temp1);
break;
case 3:
int temp2=b.getLast();
b.removeLast();
b.addLast(((int)str.charAt(j)-48)*1000+temp2);
break;
}
flag++;
j--;
}
i=j+1;
}
else { //如果为符号时
if (str.charAt(i)==')') //符号栈为空时 或者为‘)’时 直接压入符号栈
{
AtomNums atomNums=new AtomNums();
StringBuffer stringBuffer=new StringBuffer(")");
atomNums.setName(stringBuffer);
a.addLast(atomNums);
if(!(str.charAt(i-1)>='0'&&str.charAt(i-1)<='9')){
b.addLast(1);
}
}
else { //如果符号栈不是空时
if (str.charAt(i)=='('){ //如果是“(”时就需要出栈
if(b.size()>0){ //防止(H)情况出现
LinkedList<AtomNums> tempAtom=new LinkedList<>();
Integer num1=b.getLast();
while (!a.getLast().getName().toString().equals(")")){
AtomNums atomNums=a.getLast();
a.removeLast();
atomNums.setNums(atomNums.getNums()*num1);
tempAtom.addLast(atomNums);
}
b.removeLast();
a.removeLast();//删除“)”
a.addAll(tempAtom);
}
else {
LinkedList<AtomNums> tempAtom=new LinkedList<>();
Integer num1=1;
while (!a.getLast().getName().toString().equals(")")){
AtomNums atomNums=a.getLast();
a.removeLast();
atomNums.setNums(atomNums.getNums()*num1);
tempAtom.addLast(atomNums);
}
a.removeLast();//删除“)”
a.addAll(tempAtom);
}
if((i-1>0)&&!(str.charAt(i-1)>='0'&&str.charAt(i-1)<='9')&&(str.charAt(i-1)!='(')){ //判断“(”前是否是字母
b.addLast(1);
}
}
else {
StringBuffer atomNam=new StringBuffer();
//如果为元素名称时
for (int j=i;j>=0;j--){
if(str.charAt(j)>='A'&&str.charAt(j)<='Z'){
i=j;
atomNam.append(String.valueOf(str.charAt(j)));
break;
}
else {
atomNam.append(String.valueOf(str.charAt(j)));
}
}
atomNam.reverse(); //的到元素的完整名称 并加入符号栈中
AtomNums atomNums=new AtomNums();
atomNums.setName(atomNam);
atomNums.setNums(1);
//直接求原子数量
if (b.size()==0){
b.addLast(1);
}
Integer num1=b.getLast();
b.removeLast();
atomNums.setNums(num1*atomNums.getNums());
a.addLast(atomNums);
//然后判断上一个字符是否为字母 是则 并向数字栈中压入1
if (i-1>=0){
if(str.charAt(i-1)>='A'&&str.charAt(i-1)<='z'&&str.charAt(i-1)!='('){
b.addLast(1);
}
}
}
}
}
}
// System.out.println(a);
Map<String,Integer> map =new TreeMap<>();
while(a.size()>0){
if (map.get(a.getLast().getName().toString()) == null) {
map.put(a.getLast().getName().toString(), a.getLast().getNums());
} else {
map.put(a.getLast().getName().toString(), map.get(a.getLast().getName().toString()) + a.getLast().getNums());
}
a.removeLast();
}
Set keySet=map.keySet();
Iterator it = keySet.iterator();
String return_str="";
while (it.hasNext()){
Object key=it.next();
Object value=map.get(key);
if (map.get(key)>1)
return_str+=key.toString()+value.toString();
else
return_str+=key.toString();
}
return return_str;
}
}
代码看起来比较多,但是逻辑上并不复杂。