Skip to content

Commit 3593557

Browse files
feat(seo): translate 32 zh-only docs to en
补齐 32 个只有中文版的 mdx 对应的 .en.md/.en.mdx,解决 /en/ URL 时 fumadocs fallbackLanguage='zh' 兜底渲染中文内容 + 中文 description 导致 URL/description 语言不一致的 SEO 隐患。 由 translator agent (claude-sonnet-4-6) 分两批并行翻译,保留代码块、 数学公式、URL、组件名 / 非文本属性原样;frontmatter 加 lang=en / translatedFrom=zh / translatedAt / translatorAgent 4 个字段,docId 继承原文不变。 翻译范围: - 9 个分区 index.mdx(career/community/learn/projects 等) - 23 个 leetcode 题解 + 社区长文(PTE、UNSW 福利、Burnout、PPO 等) 翻译后中英对照对数从 97 → 129,zh-only 从 32 → 0。
1 parent e5de136 commit 3593557

32 files changed

Lines changed: 2509 additions & 0 deletions

content/docs/career/index.en.mdx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
title: Career
3+
description: "Involution Hell tech docs — Career section. A one-stop resource hub for the entire CS/AI job search journey: LeetCode grinding strategies, behavioral interview (BQ) and online assessment (OA) tips, plus highlights from community events like Coffee Chat and Mock Interview."
4+
date: "2026-04-18"
5+
docId: crr0001index2026041800000001
6+
lang: en
7+
translatedFrom: zh
8+
translatedAt: 2026-05-11T00:00:00Z
9+
translatorAgent: claude-sonnet-4-6
10+
---
11+
12+
import { SectionIndex } from "@/app/components/docs/SectionIndex";
13+
14+
One-stop content for the job search journey:
15+
16+
- **Interview Prep**: LeetCode grinding, BQ, OA, and Video Interview techniques
17+
- **Events**: Recaps of community events — Coffee Chat, Mock Interview, Career Journey, and more
18+
19+
<SectionIndex root="career" />
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---
2+
title: "2131. Longest Palindrome by Concatenating Two Letter Words"
3+
description: "LeetCode 2131. Longest Palindrome by Concatenating Two Letter Words — solution using a hash map to count word occurrences, pairing words with their reverses to form palindrome pairs, and checking for any self-palindrome word that can serve as the center. Great for interview prep on hash tables and palindrome problems."
4+
date: "2025/5/25-2:33"
5+
tags:
6+
- - Python
7+
- - Answer
8+
abbrlink: 9fa195e5
9+
docId: ksw2vic4alf1tdnnueay81g8
10+
lang: en
11+
translatedFrom: zh
12+
translatedAt: 2026-05-11T00:00:00Z
13+
translatorAgent: claude-sonnet-4-6
14+
---
15+
16+
# QUESTION
17+
18+
[2131. Longest Palindrome by Concatenating Two Letter Words](https://leetcode.cn/problems/longest-palindrome-by-concatenating-two-letter-words/description/?envType=daily-question&envId=2025-05-25)
19+
20+
# My Think
21+
22+
The idea comes from the brilliant Ling-nc.
23+
24+
We build a hash map to count the occurrences of each word.
25+
26+
For each word, we check whether its reverse exists in the hash map.
27+
If it does, they can form a palindrome pair — we update the result and decrease the corresponding count.
28+
If the reverse does not exist, we increment the count for the current word.
29+
Finally, we check if there's any palindromic word that can be used as the center of the palindrome.
30+
31+
Example:
32+
33+
1. Input: ["lc", "cl", "gg", "gg"]
34+
35+
2. "lc" has no pair → stored in the map: { "lc": 1 }
36+
37+
3. "cl" finds "lc" exists → use "lc" + "cl" as a pair → res += 4 → map updated to { "lc": 0 }
38+
39+
4. "gg" has no pair → stored in the map: { "lc": 0, "gg": 1 }
40+
41+
5. Second "gg" finds "gg" exists → use "gg" + "gg" as a pair → res += 4 → map becomes { "lc": 0, "gg": 0 }
42+
43+
Then we check whether the hash map contains any palindromic word (i.e., a word with two identical characters) that can be used as the center of the final palindrome string.
44+
If such a word exists, we can add 2 more to the result.
45+
46+
6. Finding a center word (can only pick one symmetric word)
47+
⚠️ In this example, all "gg" words have been paired, so none is left → no center word is added.
48+
49+
# Code
50+
51+
```python
52+
from collections import defaultdict
53+
from typing import List
54+
class Solution:
55+
def longestPalindrome(self, words: List[str]) -> int:
56+
count = defaultdict(int)
57+
res = 0
58+
for word in words:
59+
if count[word[::-1]] > 0:
60+
count[word[::-1]] -= 1
61+
res += 4
62+
else:
63+
count[word] += 1
64+
for key, value in count.items():
65+
if key[0] == key[1] and value > 0:
66+
res += 2
67+
break
68+
return res
69+
```
70+
71+
```typescript
72+
function longestPalindrome(words: string[]): number {
73+
const count: Map<string, number> = new Map();
74+
let res = 0;
75+
76+
for (const word of words) {
77+
const reversed = word.split("").reverse().join("");
78+
const reversedCount = count.get(reversed) ?? 0;
79+
80+
if (reversedCount > 0) {
81+
count.set(reversed, reversedCount - 1);
82+
res += 2 * word.length;
83+
} else {
84+
count.set(word, (count.get(word) ?? 0) + 1);
85+
}
86+
}
87+
88+
for (const [word, freq] of count.entries()) {
89+
if (word === word.split("").reverse().join("") && freq > 0) {
90+
res += word.length;
91+
break; // 只能选一个居中的回文串
92+
}
93+
}
94+
95+
return res;
96+
}
97+
```
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---
2+
title: "2241. Design an ATM Machine"
3+
description: "LeetCode 2241. Design an ATM Machine — solution using a greedy algorithm to simulate ATM deposit and withdrawal logic. The core technique is iterating denominations in reverse (500→20) with a hash map tracking banknote counts, always using the largest denomination first. Suitable for CS/AI job seekers preparing for system design interviews or practicing medium-difficulty simulation problems."
4+
date: "2025-01-06"
5+
tags:
6+
- - Python
7+
- - Answer
8+
abbrlink: a21411f
9+
docId: lzrh7ftq3kegsyx8gimonrfu
10+
lang: en
11+
translatedFrom: zh
12+
translatedAt: 2026-05-11T00:00:00Z
13+
translatorAgent: claude-sonnet-4-6
14+
---
15+
16+
# Problem
17+
18+
[2241. Design an ATM Machine](https://leetcode.cn/problems/design-an-atm-machine/description/?envType=daily-question&envId=2025-01-05)
19+
20+
There is an ATM machine that stores banknotes of 5 denominations: $20, $50, $100, $200, and $500. Initially the ATM is empty. Users can deposit or withdraw money.
21+
22+
When withdrawing, the machine prioritizes using banknotes of larger denominations.
23+
24+
For example, if you want to withdraw $300 and there are 2 $50 banknotes, 1 $100 banknote, and 1 $200 banknote, the machine will use the $100 and $200 banknotes.
25+
26+
However, if you try to withdraw $600 and there are 3 $200 banknotes and 1 $500 banknote, the request will be rejected — the machine first tries to use the $500 banknote, then cannot make up the remaining $100. Note that switching to $200 banknotes instead of the $500 is not allowed.
27+
28+
Implement the ATM class:
29+
30+
- `ATM()` initializes the ATM object.
31+
- `void deposit(int[] banknotesCount)` deposits new banknotes in the order $20, $50, $100, $200, $500.
32+
- `int[] withdraw(int amount)` returns an array of length 5 representing the number of banknotes of each denomination handed to the user (in the order $20, $50, $100, $200, $500), and updates the ATM's remaining banknotes. Returns `[-1]` if the withdrawal is impossible (no banknotes are dispensed in that case).
33+
34+
# Approach
35+
36+
The goal of this problem is to simulate an ATM — dispense exactly as much as requested, no more and no less. I use a greedy strategy, because the statement "if there are 3 `$200` banknotes and 1 `$500` banknote, the withdrawal request will be rejected" tells us we can skip the knapsack problem entirely and apply simple greedy logic.
37+
38+
Since there are only five denominations — `20`, `50`, `100`, `200`, `500` — we store them in a list and iterate as needed. We then create a `defaultdict()` to maintain a hash map of banknote counts for each denomination.
39+
40+
`deposit()` builds a reverse-order dictionary. Since we need to traverse from the largest to the smallest denomination, a reverse dictionary is very convenient here.
41+
42+
Assuming the initial `amount` is `600`, the first denomination encountered is `500`, which fits the problem's logic perfectly.
43+
44+
In the `withdraw()` function, I create a deep copy of the dictionary as a temporary store. This way, when we need to return `[-1]`, the original banknote counts remain unchanged — avoiding the need for backtracking.
45+
46+
Sylvia and I used two different traversal approaches: she iterated over the denomination list, while I iterated directly over the dictionary (effectively over its keys).
47+
48+
1. If the current amount (`600`) is greater than or equal to the current denomination (`500`), try to deduct. If all banknotes of that denomination are used up, move to the next denomination.
49+
2. If not fully used up, deduct as much as possible from `amount` and continue to the next denomination.
50+
3. If `amount` still has a remainder at the end, return `[-1]`; otherwise, calculate the total number of banknotes consumed — that is the answer.
51+
52+
# Code
53+
54+
```python
55+
import copy
56+
from typing import List
57+
58+
from collections import defaultdict
59+
60+
61+
class ATM:
62+
63+
def __init__(self):
64+
self.sd = defaultdict(int)
65+
self.amount = ['20', '50', '100', '200', '500']
66+
67+
def deposit(self, banknotesCount: List[int]) -> None:
68+
for i in range(len(banknotesCount) - 1, -1, -1):
69+
self.sd[self.amount[i]] += banknotesCount[i]
70+
71+
72+
73+
def withdraw(self, amount: int) -> List[int]:
74+
tempSd = copy.deepcopy(self.sd)
75+
# key = 面值, value = 张数
76+
for key, value in tempSd.items():
77+
if amount >= int(key) and value > 0:
78+
# 需要多少张钞票
79+
howManyPiece = amount // int(key)
80+
if howManyPiece >= value:
81+
# 全部取出来
82+
tempSd[key] = 0
83+
amount -= value * int(key)
84+
else:
85+
# 取出这么多钞票
86+
tempSd[key] -= howManyPiece
87+
amount -= int(key) * howManyPiece
88+
else:
89+
if amount > 0:
90+
return [-1]
91+
else:
92+
ans = []
93+
for i in self.sd.keys():
94+
ans.append(self.sd[i] - tempSd[i])
95+
self.sd = copy.deepcopy(tempSd)
96+
return ans[::-1]
97+
```
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
title: "2241. Design an ATM Machine"
3+
description: "LeetCode 2241. Design an ATM Machine — simulating bank ATM deposit and withdrawal logic with a focus on implementing a greedy withdrawal strategy: always use the largest denomination first (500, 200, 100, 50, 20), and handle cases where the balance is insufficient or cannot be evenly dispensed. Suitable for algorithm learners preparing for system design interviews or practicing object-oriented simulation problems."
4+
date: "2025-01-06"
5+
tags:
6+
- - Python
7+
- - Answer
8+
abbrlink: a21411f
9+
docId: lzrh7ftq3kegsyx8gimonrfu
10+
lang: en
11+
translatedFrom: zh
12+
translatedAt: 2026-05-11T00:00:00Z
13+
translatorAgent: claude-sonnet-4-6
14+
---
15+
16+
# QUESTION
17+
18+
[2241. Design an ATM Machine](https://leetcode.cn/problems/design-an-atm-machine/description/?envType=daily-question&envId=2025-01-05)
19+
20+
There is an ATM machine that stores banknotes of 5 denominations: 20, 50, 100, 200, and 500 dollars. Initially the ATM is empty. The user can use the machine to deposit or withdraw any amount of money.
21+
22+
When withdrawing, the machine prioritizes using banknotes of larger values.
23+
24+
For example, if you want to withdraw $300 and there are 2 $50 banknotes, 1 $100 banknote, and 1 $200 banknote, then the machine will use the $100 and $200 banknotes.
25+
However, if you try to withdraw $600 and there are 3 $200 banknotes and 1 $500 banknote, then the withdraw request will be rejected because the machine will first try to use the $500 banknote and then be unable to use banknotes to complete the remaining $100. Note that the machine is not allowed to use the $200 banknotes instead of the $500 banknote.
26+
27+
Implement the ATM class:
28+
29+
ATM() Initializes the ATM object.
30+
void deposit(int[] banknotesCount) Deposits new banknotes in the order $20, $50, $100, $200, and $500.
31+
int[] withdraw(int amount) Returns an array of length 5 of the number of banknotes that will be handed to the user in the order $20, $50, $100, $200, and $500, and update the number of banknotes in the ATM after withdrawing. Returns [-1] if it is not possible (do not withdraw any banknotes in this case).
32+
33+
# My Think
34+
35+
The purpose of this question is to simulate an ATM machine, which returns the amount of money you withdraw, no more and no less. I am greedy, because the second sentence "There are 3 `$200` bills and 1 `$500` bill in the machine, so the withdrawal request will be rejected"
36+
This shows that we can skip thinking about the knapsack problem in complex dynamic programming and directly consider simple greed.
37+
38+
Because the denominations of the deposited money are only `20`, `50`, `100`, `200`, `500`, we can store them in the list in advance and wait for traversal.
39+
40+
Then we create a `defaultdict()` to create a hash table for each denomination in the ATM machine.
41+
42+
`deposit()` creates a reverse traversal dictionary. Because we need to traverse the dictionary from large denominations to small denominations, the reverse dictionary is very convenient at this time.
43+
44+
Assuming the initial `amount` is `600`, the first denomination traversed is `500`, It fits the logic of the question very well.
45+
46+
For the `withdraw()` function, I created a temporary dictionary deep copy storage so that the initial array will not be changed when `[-1]` is returned. Otherwise, it will be troublesome to backtrack.
47+
48+
Here, Sylvia and I used two different traversal methods. She traversed the list of denominations, while I traversed the dictionary directly (actually traversed the key directly).
49+
50+
1. If the current denomination (`600`) is greater than the current denomination (`500`), then try to deduct it. If the bank money is withdrawn directly, then look at the next denomination.
51+
52+
2. If it is not withdrawn, then `amount` deducts the deductible share and then continues to look at the next denomination.
53+
54+
3. If there is still `amount` left at the end, return `[-1]`, otherwise calculate how many bills have been consumed in total, which is the answer.
55+
56+
# Code
57+
58+
```python
59+
import copy
60+
from typing import List
61+
62+
from collections import defaultdict
63+
64+
65+
class ATM:
66+
67+
def __init__(self):
68+
self.sd = defaultdict(int)
69+
self.amount = ['20', '50', '100', '200', '500']
70+
71+
def deposit(self, banknotesCount: List[int]) -> None:
72+
for i in range(len(banknotesCount) - 1, -1, -1):
73+
self.sd[self.amount[i]] += banknotesCount[i]
74+
75+
76+
77+
def withdraw(self, amount: int) -> List[int]:
78+
tempSd = copy.deepcopy(self.sd)
79+
# key = 面值, value = 张数
80+
for key, value in tempSd.items():
81+
if amount >= int(key) and value > 0:
82+
# 需要多少张钞票
83+
howManyPiece = amount // int(key)
84+
if howManyPiece >= value:
85+
# 全部取出来
86+
tempSd[key] = 0
87+
amount -= value * int(key)
88+
else:
89+
# 取出这么多钞票
90+
tempSd[key] -= howManyPiece
91+
amount -= int(key) * howManyPiece
92+
else:
93+
if amount > 0:
94+
return [-1]
95+
else:
96+
ans = []
97+
for i in self.sd.keys():
98+
ans.append(self.sd[i] - tempSd[i])
99+
self.sd = copy.deepcopy(tempSd)
100+
return ans[::-1]
101+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
title: "2270. Number of Ways to Split Array"
3+
description: "LeetCode 2270. Number of Ways to Split Array — solution using prefix sums and a single traversal to count valid split points. The core technique is maintaining left and right subarray sums and comparing whether the left side is greater than or equal to the right. Suitable for job seekers and beginners practicing array interval sum problems."
4+
date: "2025/1/14-9:31"
5+
tags:
6+
- - Python
7+
- - Answer
8+
abbrlink: c25bb550
9+
docId: a6inw303oslb7i5tcqj5xxx4
10+
lang: en
11+
translatedFrom: zh
12+
translatedAt: 2026-05-11T00:00:00Z
13+
translatorAgent: claude-sonnet-4-6
14+
---
15+
16+
# Problem
17+
18+
[2270. Number of Ways to Split Array](https://leetcode.cn/problems/number-of-ways-to-split-array/description/)
19+
20+
# Approach
21+
22+
`2 <= nums.length <= 10^5`, so we can directly take the first element. The initial state has the pointer at index 0, about to move to index 1. A single `for` loop is all we need.
23+
24+
The second method is the key one — taken from the editorial.
25+
26+
# Code
27+
28+
```python
29+
class Solution:
30+
def waysToSplitArray(self, nums: List[int]) -> int:
31+
temp_sum = nums[0]
32+
total_sum = sum(nums) - temp_sum
33+
ans = 0
34+
for i in range(1, len(nums)):
35+
if temp_sum >= total_sum:
36+
ans += 1
37+
temp_sum += nums[i]
38+
total_sum -= nums[i]
39+
return ans
40+
```
41+
42+
```python
43+
t = (sum(nums) + 1) // 2
44+
return sum(s >= t for s in accumulate(nums[:-1]))
45+
```

0 commit comments

Comments
 (0)