Сложность: hard
Если задана строковая формула, представляющая химическую формулу, верните количество атомов. Атомный элемент всегда начинается с прописного символа, затем ноль или более строчных букв, представляющих его название. Если количество больше 1, за ним может следовать одна или более цифр, представляющих количество элементов. Например, "H2O" и "H2O2" возможны, а "H1O2" невозможен. Две формулы объединяются вместе, чтобы получить другую формулу. Например, "H2O2He3Mg4" также является формулой.
Формула, заключенная в круглые скобки, и счет (по желанию) также являются формулами. Например, "(H2O2)" и "(H2O2)3" являются формулами.
Возвращает количество всех элементов в виде строки в следующем виде: первое имя (в отсортированном порядке), затем его количество (если это количество больше 1), затем второе имя (в отсортированном порядке), затем его количество (если это количество больше 1) и т. д. Тестовые примеры генерируются таким образом, чтобы все значения в выводе помещались в 32-битное целое число.
Пример:
Input: formula = "H2O"
Output: "H2O"
👨💻 Алгоритм:
1⃣Используйте стек для отслеживания текущего уровня скобок.
2⃣Пройдите по строке формулы, анализируя каждый символ: Если символ - это открывающая скобка '(', создайте новый словарь для хранения атомов внутри скобок. Если символ - это закрывающая скобка ')', извлеките словарь из стека и умножьте количества атомов на последующее число, если оно присутствует. Если символ - это атом (начинается с заглавной буквы), извлеките имя атома и его количество, и добавьте его в текущий словарь.
3⃣После завершения обработки строки, объедините все словари из стека и отсортируйте результат.
😎 Решение:
public class Solution {
public string CountOfAtoms(string formula) {
var stack = new Stack<Dictionary<string, int>>();
stack.Push(new Dictionary<string, int>());
int n = formula.Length;
int i = 0;
while (i < n) {
if (formula[i] == '(') {
stack.Push(new Dictionary<string, int>());
i++;
} else if (formula[i] == ')') {
var top = stack.Pop();
i++;
int start = i;
while (i < n && Char.IsDigit(formula[i])) {
i++;
}
int multiplicity = i > start ? int.Parse(formula.Substring(start, i - start)) : 1;
foreach (var name in top.Keys) {
int count = top[name];
if (stack.Peek().ContainsKey(name)) {
stack.Peek()[name] += count * multiplicity;
} else {
stack.Peek()[name] = count * multiplicity;
}
}
} else {
int start = i;
i++;
while (i < n && Char.IsLower(formula[i])) {
i++;
}
string name = formula.Substring(start, i - start);
start = i;
while (i < n && Char.IsDigit(formula[i])) {
i++;
}
int multiplicity = i > start ? int.Parse(formula.Substring(start, i - start)) : 1;
if (stack.Peek().ContainsKey(name)) {
stack.Peek()[name] += multiplicity;
} else {
stack.Peek()[name] = multiplicity;
}
}
}
var countMap = stack.Pop();
var sb = new StringBuilder();
foreach (var name in countMap.Keys.OrderBy(x => x)) {
sb.Append(name);
int count = countMap[name];
if (count > 1) {
sb.Append(count);
}
}
return sb.ToString();
}
}Ставь 👍 и забирай 📚 Базу знаний