Given a string formula representing a chemical formula, return the count of each atom.
The atomic element always starts with an uppercase character, then zero or more lowercase letters, representing the name. One or more digits representing that element's count may follow if the count is greater than 1. If the count is 1, no digits will follow.
For example, "H2O" and "H2O2" are possible, but "H1O2" is impossible.
Two formulas are concatenated together to produce another formula. For example, "H2O2He3Mg4" is also a formula.
A formula placed in parentheses, and a count (optionally added) is also a formula. For example, "(H2O2)" and "(H2O2)3" are formulas.
Return the count of all elements as a string in the following form: the first name (in sorted order), followed by its count (if that count is more than 1), followed by the second name (in sorted order), followed by its count (if that count is more than 1), and so on.
The key insight is using a stack to handle nested parentheses naturally. Each stack level maintains element counts, and when closing parentheses are encountered, counts are multiplied and merged with the parent level. Best approach is stack-based parsing in O(n) time with O(n) space.
Common Approaches
✓
Stack-Based Parsing
⏱️ Time: O(n)
Space: O(n)
Parse the formula character by character, using a stack to handle nested parentheses. Each stack level maintains a count map, and when we encounter closing parentheses, we multiply counts and merge with parent level.
String Expansion Approach
⏱️ Time: O(n³)
Space: O(n³)
First expand all parentheses by replacing (formula)n with formula repeated n times, then parse the expanded string to count atoms. This approach handles nesting by expanding innermost parentheses first.
Stack-Based Parsing — Algorithm Steps
Step 1: Initialize stack with empty count map
Step 2: Parse elements and counts normally
Step 3: On '(', push new map to stack
Step 4: On ')', pop map, multiply by following number, merge with parent
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Push on '('
Create new count level
2
Parse Elements
Add to current level
3
Pop on ')'
Multiply and merge up
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_ELEMENTS 1000
#define MAX_NAME_LEN 20
#define MAX_STACK_SIZE 100
typedef struct {
char name[MAX_NAME_LEN];
int count;
} Element;
typedef struct {
Element elements[MAX_ELEMENTS];
int size;
} ElementMap;
ElementMap stack[MAX_STACK_SIZE];
int stackTop = -1;
void pushMap() {
stackTop++;
stack[stackTop].size = 0;
}
ElementMap popMap() {
ElementMap result = stack[stackTop];
stackTop--;
return result;
}
ElementMap* topMap() {
return &stack[stackTop];
}
void addElement(ElementMap* map, const char* name, int count) {
for (int i = 0; i < map->size; i++) {
if (strcmp(map->elements[i].name, name) == 0) {
map->elements[i].count += count;
return;
}
}
strcpy(map->elements[map->size].name, name);
map->elements[map->size].count = count;
map->size++;
}
int parseInt(const char* str, int start, int end) {
if (start >= end) return 1;
char temp[20];
strncpy(temp, str + start, end - start);
temp[end - start] = '\0';
return atoi(temp);
}
void substring(const char* str, int start, int end, char* result) {
strncpy(result, str + start, end - start);
result[end - start] = '\0';
}
int compareElements(const void* a, const void* b) {
const Element* ea = (const Element*)a;
const Element* eb = (const Element*)b;
return strcmp(ea->name, eb->name);
}
char* solution(char* formula) {
static char result[2000];
stackTop = -1;
pushMap();
int i = 0;
int len = strlen(formula);
while (i < len) {
if (formula[i] == '(') {
pushMap();
i++;
} else if (formula[i] == ')') {
i++;
int start = i;
while (i < len && isdigit(formula[i])) {
i++;
}
int multiplier = (start < i) ? parseInt(formula, start, i) : 1;
ElementMap currentCounts = popMap();
ElementMap* parent = topMap();
for (int j = 0; j < currentCounts.size; j++) {
addElement(parent, currentCounts.elements[j].name, currentCounts.elements[j].count * multiplier);
}
} else if (isupper(formula[i])) {
int start = i;
i++;
while (i < len && islower(formula[i])) {
i++;
}
char element[MAX_NAME_LEN];
substring(formula, start, i, element);
int countStart = i;
while (i < len && isdigit(formula[i])) {
i++;
}
int count = (countStart < i) ? parseInt(formula, countStart, i) : 1;
addElement(topMap(), element, count);
} else {
i++;
}
}
ElementMap* counts = topMap();
qsort(counts->elements, counts->size, sizeof(Element), compareElements);
result[0] = '\0';
for (int i = 0; i < counts->size; i++) {
strcat(result, counts->elements[i].name);
if (counts->elements[i].count > 1) {
char countStr[20];
sprintf(countStr, "%d", counts->elements[i].count);
strcat(result, countStr);
}
}
return result;
}
int main() {
char formula[1000];
fgets(formula, sizeof(formula), stdin);
formula[strcspn(formula, "\n")] = 0;
char* result = solution(formula);
printf("%s\n", result);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n)
Single pass through the formula string, each character processed once
n
2n
✓ Linear Growth
Space Complexity
O(n)
Stack depth proportional to nesting level, count maps store unique elements
n
2n
⚡ Linearithmic Space
89.5K Views
MediumFrequency
~25 minAvg. Time
1.8K Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.