28、原子的数量

题目描述:
给定一个化学式formula(作为字符串),返回每种原子的数量。

原子总是以一个大写字母开始,接着跟随0个或任意个小写字母,表示原子的名字。

如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如,H2O 和 H2O2 是可行的,但 H1O2 这个表达是不可行的。

两个化学式连在一起是新的化学式。例如 H2O2He3Mg4 也是化学式。

一个括号中的化学式和数字(可选择性添加)也是化学式。例如 (H2O2) 和 (H2O2)3 是化学式。

给定一个化学式,输出所有原子的数量。格式为:第一个(按字典序)原子的名子,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。

示例 1:

输入:
formula = “H2O”
输出: “H2O”
解释:
原子的数量是 {‘H’: 2, ‘O’: 1}。
示例 2:

输入:
formula = “Mg(OH)2”
输出: “H2MgO2”
解释:
原子的数量是 {‘H’: 2, ‘Mg’: 1, ‘O’: 2}。
示例 3:

输入:
formula = “K4(ON(SO3)2)2”
输出: “K4N2O14S4”
解释:
原子的数量是 {‘K’: 4, ‘N’: 2, ‘O’: 14, ‘S’: 4}。
注意:

所有原子的第一个字母为大写,剩余字母都是小写。
formula的长度在[1, 1000]之间。
formula只包含字母、数字和圆括号,并且题目中给定的是合法的化学式。
用传统思路写:
代码:明显会超时

import java.util.Map.Entry;
import java.util.Stack;
import java.util.TreeMap;
class Solution {
    public String countOfAtoms(String formula) {
    	
    	Stack<Character> stack = new Stack<>();
    	char tem[] = formula.toCharArray();
    	StringBuilder sb = new StringBuilder();
    	for (int i = 0; i < tem.length;) {
			char c = tem[i];
			if(c == ')'){
				StringBuilder tem1 = new StringBuilder();
				while (!stack.isEmpty() && stack.peek() != '(') {
					tem1.append(stack.pop());
				}
				stack.pop();
				int [] get = gettime(formula, i + 1);
				i = get[1];
				int time = get[0] - 1;
				StringBuilder tem2 = new StringBuilder(tem1);
				for (int j = 0; j < time; j++) {
					tem1.append(tem2);
				}
				for (int j =  tem1.length() - 1; j >= 0; j--) {
					stack.push(tem1.charAt(j));
				}
			}else {
				stack.push(c);
                i++;
			}
		}
    	StringBuilder sBuilder = new StringBuilder();
    	while (!stack.isEmpty()) {
			sBuilder.append(stack.pop());
		}
    	TreeMap<String, Integer> map = new TreeMap<>();
    	sBuilder.reverse();
    	int start = 0;
    	for (int i = 0; i < sBuilder.length();) {
    		char c = sBuilder.charAt(i);
    		if(i == sBuilder.length() - 1){
    			int [] gets = gettime(sBuilder.toString(), i + 1);
    			i = gets[1];
    			int time = gets[0];
    			map.put(c + "", map.getOrDefault(c + "", 0) + time);
    		}else {
				if(sBuilder.charAt(i + 1) >= 'a' && sBuilder.charAt(i + 1) <= 'z'){
					String str = c + "" +sBuilder.charAt(i + 1) + "";
					int [] gets = gettime(sBuilder.toString(), i + 2);
	    			i = gets[1];
	    			int time = gets[0];
	    			map.put(str, map.getOrDefault(str, 0) + time);
				}else {
					int [] gets = gettime(sBuilder.toString(), i + 1);
	    			i = gets[1];
	    			int time = gets[0];
	    			map.put(c + "", map.getOrDefault(c + "", 0) + time);
				}
	
    		}
		}
        StringBuilder result = new StringBuilder();
    	for (Entry<String, Integer> c : map.entrySet()) {
    		result.append(c.getKey());
			if(c.getValue() == 1){
				continue;
			}else {
				result.append(c.getValue());
				continue;
			}
		}
    	   	
    	return result.toString();
        
    }
   public int[] gettime(String str,int index){
    	int tem = index;
    	while (index < str.length() && str.charAt(index) <= '9' &&
    			str.charAt(index) >= '0') {
			index ++;
		}
    	if(index == tem){
    		return new int[]{1,index};
    	}
    	return new int[]{Integer.valueOf(str.substring(tem, index)),index};
    }
     
}

参考别人的思路,哎
整了半天还超时
LeetCode 原子的数量(递归+hash表)

参考别人的思路解法

public String countOfAtoms(String formula) {
		if (!formula.contains("(")) {
			TreeMap<String, Integer> map = new TreeMap<>();
			String atom = "";
			int len = 0;

			char[] chars = formula.toCharArray();
			atom = "" + chars[0];
			for (int i = 1; i < chars.length; i++) {
				if (Character.isUpperCase(chars[i])) {
					len = len == 0 ? 1 : len;
					if (map.containsKey(atom)) {
						map.put(atom, map.get(atom) + len);
					} else {
						map.put(atom, len);
					}
					len = 0;
					atom = "" + chars[i];

					continue;
				}
				if (Character.isLowerCase(chars[i])) {
					atom += chars[i];
					continue;
				}

				len = len * 10 + Character.getNumericValue(chars[i]);
			}

			len = len == 0 ? 1 : len;
			if (map.containsKey(atom)) {
				map.put(atom, map.get(atom) + len);
			} else {
				map.put(atom, len);
			}

			// calc
			StringBuilder sb = new StringBuilder();
			map.forEach((k, v) -> {
				sb.append(k);
				if (v > 1) {
					sb.append(v);
				}
			});
			return sb.toString();
		}

		if (formula.contains("(")) {
			int end = formula.indexOf(")");
			int begin = formula.lastIndexOf("(", end);

			int temp = 0;
			int cur = end + 1;
			while (cur < formula.length() && Character.isDigit(formula.charAt(cur))) {
				temp = temp * 10 + Character.getNumericValue(formula.charAt(cur));
				cur++;
			}

			if (temp == 0) {
				temp = 1;
			}
			String ff = flat(formula.substring(begin + 1, end), temp);

			formula = formula.substring(0, begin) + ff + formula.substring(cur);
		}
		return countOfAtoms(formula);
	}

	private String flat(String formula, int repeat) {
		char[] cs = formula.toCharArray();

		int temp = 0;
		StringBuilder sb = new StringBuilder();
		sb.append(cs[0]);
		for (int i = 1; i < cs.length; i++) {
			if (Character.isUpperCase(cs[i])) {
				if (temp == 0) {
					sb.append(repeat);
				} else {
					sb.append(temp * repeat);
				}
				temp = 0;
			}

			if (Character.isLetter(cs[i])) {
				sb.append(cs[i]);
				continue;
			}

			temp = temp * 10 + Character.getNumericValue(cs[i]);
		}

		if (temp == 0) {
			sb.append(repeat);
		} else {
			sb.append(repeat * temp);
		}

		return sb.toString();
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值