Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8a5014f

Browse files
Merge pull request SharingSource#36 from SharingSource/ac_oier
✨feat: Add 726
2 parents 4146e9f + adb6b42 commit 8a5014f

File tree

5 files changed

+192
-0
lines changed

5 files changed

+192
-0
lines changed

‎Index/哈希表.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
| [697. 数组的度](https://leetcode-cn.com/problems/degree-of-an-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/degree-of-an-array/solution/shu-zu-ji-shu-ha-xi-biao-ji-shu-jie-fa-y-a0mg/) | 简单 | 🤩🤩🤩 |
1717
| [705. 设计哈希集合](https://leetcode-cn.com/problems/design-hashset/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/design-hashset/solution/yi-ti-san-jie-jian-dan-shu-zu-lian-biao-nj3dg/) | 简单 | 🤩🤩🤩🤩 |
1818
| [706. 设计哈希映射](https://leetcode-cn.com/problems/design-hashmap/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/design-hashmap/solution/yi-ti-shuang-jie-jian-dan-shu-zu-lian-bi-yhiw/) | 简单 | 🤩🤩🤩🤩 |
19+
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
1920
| [888. 公平的糖果棒交换](https://leetcode-cn.com/problems/fair-candy-swap/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fair-candy-swap/solution/gong-shui-san-xie-yi-ti-shuang-jie-po-su-uant/) | 简单 | 🤩🤩 |
2021
| [1074. 元素和为目标值的子矩阵数量](https://leetcode-cn.com/problems/number-of-submatrices-that-sum-to-target/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-submatrices-that-sum-to-target/solution/gong-shui-san-xie-you-hua-mei-ju-de-ji-b-uttw/) | 困难 | 🤩🤩🤩 |
2122
| [1178. 猜字谜](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/solution/xiang-jin-zhu-shi-xiang-jie-po-su-wei-yu-3cr2/) | 困难 | 🤩🤩🤩🤩 |

‎Index/堆.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
| [480. 滑动窗口中位数](https://leetcode-cn.com/problems/sliding-window-median/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sliding-window-median/solution/xiang-jie-po-su-jie-fa-you-xian-dui-lie-mo397/) | 困难 | 🤩🤩🤩🤩 |
77
| [692. 前K个高频单词](https://leetcode-cn.com/problems/top-k-frequent-words/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/top-k-frequent-words/solution/gong-shui-san-xie-xiang-jie-shi-yong-ha-8dxt2/) | 中等 | 🤩🤩🤩🤩 |
88
| [703. 数据流中的第 K 大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/jian-da-ti-de-duo-chong-jie-fa-mou-pao-p-d1qi/) | 简单 | 🤩🤩🤩 |
9+
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
910

‎Index/栈.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| [155. 最小栈](https://leetcode-cn.com/problems/min-stack/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/min-stack/solution/tu-li-zhan-shi-shuang-zhan-shi-xian-zui-fcwj5/) | 简单 | 🤩🤩🤩🤩🤩 |
66
| [232. 用栈实现队列](https://leetcode-cn.com/problems/implement-queue-using-stacks/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/implement-queue-using-stacks/solution/sha-shi-jun-tan-fu-za-du-ya-wo-de-suan-f-gb6d/) | 简单 | 🤩🤩🤩🤩🤩 |
77
| [341. 扁平化嵌套列表迭代器](https://leetcode-cn.com/problems/flatten-nested-list-iterator/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/flatten-nested-list-iterator/solution/yi-ti-shuang-jie-dfsdui-lie-di-gui-zhan-kvwhy/) | 中等 | 🤩🤩🤩 |
8+
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
89
| [1190. 反转每对括号间的子串](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/gong-shui-san-xie-shi-yong-shuang-duan-d-r35q/) | 中等 | 🤩🤩🤩🤩🤩 |
910
| [面试题 03.01. 三合一](https://leetcode-cn.com/problems/three-in-one-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/three-in-one-lcci/solution/yi-ti-shuang-jie-er-wei-shu-zu-yi-wei-sh-lih7/) | 简单 | 🤩🤩🤩 |
1011

‎Index/模拟.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
| [451. 根据字符出现频率排序](https://leetcode-cn.com/problems/sort-characters-by-frequency/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sort-characters-by-frequency/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-gst9/) | 中等 | 🤩🤩🤩🤩 |
2222
| [566. 重塑矩阵](https://leetcode-cn.com/problems/reshape-the-matrix/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reshape-the-matrix/solution/jian-dan-ti-zhong-quan-chu-ji-ke-yi-kan-79gv5/) | 简单 | 🤩🤩🤩 |
2323
| [645. 错误的集合](https://leetcode-cn.com/problems/set-mismatch/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/set-mismatch/solution/gong-shui-san-xie-yi-ti-san-jie-ji-shu-s-vnr9/) | 简单 | 🤩🤩🤩 |
24+
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
2425
| [766. 托普利茨矩阵](https://leetcode-cn.com/problems/toeplitz-matrix/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/toeplitz-matrix/solution/cong-ci-pan-du-qu-cheng-ben-fen-xi-liang-f20w/) | 简单 | 🤩🤩🤩 |
2526
| [867. 转置矩阵](https://leetcode-cn.com/problems/transpose-matrix/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/transpose-matrix/solution/yi-you-wei-jin-huo-xu-ni-neng-kan-kan-zh-m53m/) | 简单 | 🤩🤩🤩🤩 |
2627
| [896. 单调数列](https://leetcode-cn.com/problems/monotonic-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/monotonic-array/solution/wei-shi-yao-yi-ci-bian-li-yao-bi-liang-c-uglp/) | 简单 | 🤩🤩🤩🤩 |
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/)** ,难度为 **困难**
4+
5+
Tag : 「模拟」、「数据结构运用」、「栈」、「哈希表」、「优先队列」
6+
7+
8+
9+
给定一个化学式 `formula`(作为字符串),返回每种原子的数量。
10+
11+
原子总是以一个大写字母开始,接着跟随0个或任意个小写字母,表示原子的名字。
12+
13+
如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如,`H2O``H2O2` 是可行的,但 `H1O2` 这个表达是不可行的。
14+
15+
两个化学式连在一起是新的化学式。例如 `H2O2He3Mg4` 也是化学式。
16+
17+
一个括号中的化学式和数字(可选择性添加)也是化学式。例如 `(H2O2)``(H2O2)3` 是化学式。
18+
19+
给定一个化学式,输出所有原子的数量。格式为:第一个(按字典序)原子的名子,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。
20+
21+
示例 1:
22+
```
23+
输入: formula = "H2O"
24+
25+
输出: "H2O"
26+
27+
解释: 原子的数量是 {'H': 2, 'O': 1}。
28+
```
29+
示例 2:
30+
```
31+
输入: formula = "Mg(OH)2"
32+
33+
输出: "H2MgO2"
34+
35+
解释: 原子的数量是 {'H': 2, 'Mg': 1, 'O': 2}。
36+
```
37+
示例 3:
38+
```
39+
输入: formula = "K4(ON(SO3)2)2"
40+
41+
输出: "K4N2O14S4"
42+
43+
解释: 原子的数量是 {'K': 4, 'N': 2, 'O': 14, 'S': 4}。
44+
```
45+
46+
注意:
47+
* 所有原子的第一个字母为大写,剩余字母都是小写。
48+
* `formula` 的长度在[1, 1000]之间。
49+
* `formula` 只包含字母、数字和圆括号,并且题目中给定的是合法的化学式。
50+
51+
---
52+
53+
### 数据结构 + 模拟
54+
55+
一道综合模拟题。
56+
57+
相比于[(题解)227. 基本计算器 II](https://leetcode-cn.com/problems/basic-calculator-ii/solution/shi-yong-shuang-zhan-jie-jue-jiu-ji-biao-c65k/) 的表达式计算问题,本题设计模拟流程的难度要低很多,之所谓定位困难估计是使用到的数据结构较多一些。
58+
59+
为了方便,我们约定以下命名:
60+
* 称一段完整的连续字母为「原子」
61+
* 称一段完整的连续数字为「数值」
62+
*`(``)` 为「符号」
63+
64+
基本实现思路如下:
65+
66+
1. 在处理入参 `s` 的过程中,始终维护着一个哈希表 `map`,`map`**实时维护** 着某个「原子」对应的实际「数值」(即存储格式为 `{H:2,S:1}`);
67+
68+
> 由于相同原子可以出在 `s` 的不同位置中,为了某个「数值」对「原子」的累乘效果被重复应用,我们这里应用一个"小技巧":为每个「原子」增加一个"编号后缀"。即实际存储时为 `{H_1:2, S_2:1, H_3:1}`
69+
70+
2. 根据当前处理到的字符分情况讨论:
71+
* 符号:直接入栈;
72+
* 原子:继续往后取,直到取得完整的原子名称,将完整原子名称入栈,同时在 `map` 中计数加 1ドル$;
73+
* 数值:继续往后取,直到取得完整的数值并解析,然后根据栈顶元素是否为 `)` 符号,决定该数值应用给哪些原子:
74+
* 如果栈顶元素不为 `)`,说明该数值只能应用给栈顶的原子
75+
* 如果栈顶元素是 ),说明当前数值可以应用给「连续一段」的原子中
76+
77+
3.`map` 的原子做 "合并" 操作:`{H_1:2, S_2:1, H_3:1}` => `{H:3, S:1}` ;
78+
79+
4. 使用「优先队列(堆)」实现字典序排序(也可以直接使用 `List`,然后通过 `Collections.sort` 进行排序),并构造答案。
80+
81+
代码:
82+
```Java []
83+
class Solution {
84+
class Node {
85+
String s; int v;
86+
Node (String _s, int _v) {
87+
s = _s; v = _v;
88+
}
89+
}
90+
public String countOfAtoms(String s) {
91+
int n = s.length();
92+
char[] cs = s.toCharArray();
93+
Map<String, Integer> map = new HashMap<>();
94+
Deque<String> d = new ArrayDeque<>();
95+
int idx = 0;
96+
for (int i = 0; i < n; ) {
97+
char c = cs[i];
98+
if (c == '(' || c == ')') {
99+
d.addLast(String.valueOf(c));
100+
i++;
101+
} else {
102+
if (Character.isDigit(c)) {
103+
// 获取完整的数字,并解析出对应的数值
104+
int j = i;
105+
while (j < n && Character.isDigit(cs[j])) j++;
106+
String numStr = s.substring(i, j);
107+
i = j;
108+
int cnt = Integer.parseInt(String.valueOf(numStr));
109+
110+
// 如果栈顶元素是 ),说明当前数值可以应用给「连续一段」的原子中
111+
if (!d.isEmpty() && d.peekLast().equals(")")) {
112+
List<String> tmp = new ArrayList<>();
113+
114+
d.pollLast(); // pop )
115+
while (!d.isEmpty() && !d.peekLast().equals("(")) {
116+
String cur = d.pollLast();
117+
map.put(cur, map.getOrDefault(cur, 1) * cnt);
118+
tmp.add(cur);
119+
}
120+
d.pollLast(); // pop (
121+
122+
for (int k = tmp.size() - 1; k >= 0; k--) {
123+
d.addLast(tmp.get(k));
124+
}
125+
126+
// 如果栈顶元素不是 ),说明当前数值只能应用给栈顶的原子
127+
} else {
128+
String cur = d.pollLast();
129+
map.put(cur, map.getOrDefault(cur, 1) * cnt);
130+
d.addLast(cur);
131+
}
132+
} else {
133+
// 获取完整的原子名
134+
int j = i + 1;
135+
while (j < n && Character.isLowerCase(cs[j])) j++;
136+
String cur = s.substring(i, j) + "_" + String.valueOf(idx++);
137+
map.put(cur, map.getOrDefault(cur, 0) + 1);
138+
i = j;
139+
d.addLast(cur);
140+
}
141+
}
142+
}
143+
144+
// 将不同编号的相同原子进行合并
145+
Map<String, Node> mm = new HashMap<>();
146+
for (String key : map.keySet()) {
147+
String atom = key.split("_")[0];
148+
int cnt = map.get(key);
149+
Node node = null;
150+
if (mm.containsKey(atom)) {
151+
node = mm.get(atom);
152+
} else {
153+
node = new Node(atom, 0);
154+
}
155+
node.v += cnt;
156+
mm.put(atom, node);
157+
}
158+
159+
// 使用优先队列(堆)对 Node 进行字典序排序,并构造答案
160+
PriorityQueue<Node> q = new PriorityQueue<Node>((a,b)->a.s.compareTo(b.s));
161+
for (String atom : mm.keySet()) q.add(mm.get(atom));
162+
163+
StringBuilder sb = new StringBuilder();
164+
while (!q.isEmpty()) {
165+
Node poll = q.poll();
166+
sb.append(poll.s);
167+
if (poll.v > 1) sb.append(poll.v);
168+
}
169+
170+
return sb.toString();
171+
}
172+
}
173+
```
174+
* 时间复杂度:最坏情况下,每次处理数值都需要从栈中取出元素进行应用,处理 `s` 的复杂度为 $O(n^2)$;最坏情况下,每个原子独立分布,合并的复杂度为 $O(n)$;将合并后的内容存入优先队列并取出构造答案的复杂度为 $O(n\log{n})$;整体复杂度为 $O(n^2)$
175+
* 空间复杂度:$O(n)$
176+
177+
---
178+
179+
### 最后
180+
181+
这是我们「刷穿 LeetCode」系列文章的第 `No.726` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
182+
183+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
184+
185+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
186+
187+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
188+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /