技藝競賽選手培訓期間刷題合集

53k 詞

按題號排序,包含原題說明、解題邏輯與程式碼。(注:題號不代表難度)
僅提供過去筆記中有所紀錄的題目
總計 leetcode 116 題 + APCS 歷屆考題 8 題


1. Two Sum

日期: 2025/02/05 | 難度: Easy | 分類: 雜湊表

題目說明

給一個整數陣列 nums 和目標值 target,找出兩個數的索引使其和等於 target。

解題邏輯

用字典記錄「已見過的數 → 其索引」。遍歷時,檢查 target - n 是否在字典中,若在則直接回傳兩個索引。只需一次遍歷,時間複雜度 O(n)。

1
2
3
4
5
6
7
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d = {}
for j, n in enumerate(nums):
if target - n in d:
return [d[target - n], j]
d[n] = j

3. Longest Substring Without Repeating Characters

日期: 2025/01/15 | 難度: Medium | 分類: 滑動視窗、雜湊表

題目說明

給一個字串 s,找出不含重複字元的最長子字串長度。

解題邏輯

滑動視窗:用集合記錄視窗內的字元,右指針擴張時若遇重複字元,就從左收縮直到不重複,持續更新最大長度。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
st = set()
l = 0
m = 0
for r in range(len(s)):
while s[r] in st:
st.remove(s[l])
l += 1
st.add(s[r])
m = max(m, r - l + 1)
return m

9. Palindrome Number

日期: 2024/12/20 | 難度: Easy | 分類: 數學

題目說明

給一個整數 x,判斷它是否為回文數。

解題邏輯

轉成字串後與反轉版本比較。

1
2
3
class Solution:
def isPalindrome(self, x: int) -> bool:
return str(x) == str(x)[::-1]

11. Container With Most Water

日期: 2025/02/05 | 難度: Medium | 分類: 雙指針

題目說明

給一個高度陣列,選兩條線使其與 x 軸圍成的容器能裝最多水。

解題邏輯

雙指針從兩端向中間夾,每次移動較短的那一側(因為移動較長的只會讓寬度縮短且高度不增),持續更新最大面積。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def maxArea(self, height: List[int]) -> int:
l, r = 0, len(height) - 1
m = 0
while l < r:
i = min(height[l], height[r]) * (r - l)
m = max(m, i)
if height[l] <= height[r]:
l += 1
else:
r -= 1
return m

13. Roman to Integer

日期: 2024/12/21 | 難度: Easy | 分類: 字串、數學

題目說明

將羅馬數字字串轉換為整數。羅馬數字中若小值在大值左側,則為減法(如 IV = 4)。

解題邏輯

建立羅馬字母對應值的字典。遍歷字串,若當前值小於下一個值則減去,否則加上。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def romanToInt(self, s: str) -> int:
d = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
ans = 0
for i in range(len(s) - 1):
now = d[s[i]]
nex = d[s[i + 1]]
if now >= nex:
ans += now
else:
ans -= now
ans += d[s[-1]]
return ans

14. Longest Common Prefix

日期: 2024/12/21 | 難度: Easy | 分類: 字串

題目說明

找出字串陣列中所有字串的最長公共前綴。

解題邏輯

以第一個字串為基準,逐字元與其他字串比較,若某字元不匹配或某字串已結束,則回傳目前前綴。

1
2
3
4
5
6
7
8
9
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs:
return ""
for i in range(len(strs[0])):
for s in strs[1:]:
if i >= len(s) or s[i] != strs[0][i]:
return strs[0][:i]
return strs[0]

22. Generate Parentheses

日期: 2025/01/24 | 難度: Medium | 分類: 回溯、遞迴

題目說明

給 n,生成所有合法的 n 對括號組合。

解題邏輯

回溯法:追蹤已放的左括號數 open 和右括號數 close,只在 open < n 時加左括號,只在 close < open 時加右括號,長度達 2n 時加入結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
res = []
def f(s, open, close):
if len(s) == 2 * n:
res.append(s)
return
if open < n:
f(s + '(', open + 1, close)
if close < open:
f(s + ')', open, close + 1)
f('', 0, 0)
return res

26. Remove Duplicates from Sorted Array

日期: 2024/12/15 | 難度: Easy | 分類: 陣列、雙指針

題目說明

已排序陣列原地去除重複元素,回傳不重複元素數量 k。

解題邏輯

用 set 去重後排序,覆寫回陣列前段,回傳長度。

1
2
3
4
5
6
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
l = sorted(set(nums))
for i in range(len(l)):
nums[i] = l[i]
return len(l)

27. Remove Element

日期: 2024/12/22 | 難度: Easy | 分類: 陣列、雙指針

題目說明

原地移除陣列中所有等於 val 的元素,回傳剩餘長度。

解題邏輯

雙指針:k 追蹤下一個有效位置,遍歷時遇到非 val 元素就放到 nums[k] 並移動 k。

1
2
3
4
5
6
7
8
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
k = 0
for i in range(len(nums)):
if nums[i] != val:
nums[k] = nums[i]
k += 1
return k

28. Find the Index of the First Occurrence in a String

日期: 2024/12/23 | 難度: Easy | 分類: 字串

題目說明

haystack 中找 needle 第一次出現的索引,找不到回傳 -1。

解題邏輯

直接使用 Python 內建 find() 方法。

1
2
3
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
return haystack.find(needle)

36. Valid Sudoku

日期: 2025/01/16 | 難度: Medium | 分類: 雜湊表、陣列

題目說明

判斷一個 9x9 數獨棋盤是否合法(行、列、3x3 方格各不重複非空格數字)。

解題邏輯

分別用集合驗證每行、每列、每個 3x3 子方格是否有重複數字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
rows = [set() for _ in range(9)]
cols = [set() for _ in range(9)]
boxes = [set() for _ in range(9)]
for i in range(9):
for j in range(9):
val = board[i][j]
if val == '.':
continue
box_idx = (i // 3) * 3 + j // 3
if val in rows[i] or val in cols[j] or val in boxes[box_idx]:
return False
rows[i].add(val)
cols[j].add(val)
boxes[box_idx].add(val)
return True

39. Combination Sum

日期: 2024/12/31 | 難度: Medium | 分類: 回溯

題目說明

給一個不重複候選數陣列 candidates 和目標值 target,找出所有能組合出 target 的組合(數字可重複使用)。

解題邏輯

回溯:從當前索引開始選數,每次可重複選同一個數(繼續從 i 開始),當 target == 0 時記錄結果,超過則剪枝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res = []
def f(start, path, remain):
if remain == 0:
res.append(path[:])
return
for i in range(start, len(candidates)):
if candidates[i] > remain:
continue
path.append(candidates[i])
f(i, path, remain - candidates[i])
path.pop()
f(0, [], target)
return res

40. Combination Sum II

日期: 2024/12/31 | 難度: Medium | 分類: 回溯

題目說明

候選數有重複,每個數只能用一次,找出所有和為 target 的組合(結果不能重複)。

解題邏輯

先排序,回溯時跳過同層重複的數(i > start and candidates[i] == candidates[i-1] 時跳過),避免重複組合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
res = []
def f(start, path, remain):
if remain == 0:
res.append(path[:])
return
for i in range(start, len(candidates)):
if candidates[i] > remain:
break
if i > start and candidates[i] == candidates[i - 1]:
continue
path.append(candidates[i])
f(i + 1, path, remain - candidates[i])
path.pop()
f(0, [], target)
return res

43. Multiply Strings

日期: 2025/01/24 | 難度: Medium | 分類: 數學、字串

題目說明

給兩個以字串表示的非負整數,回傳其乘積(也以字串表示),不能直接轉 int。

解題邏輯

模擬手算乘法:用一個長度 m+n 的陣列存中間結果,nums1[i] * nums2[j] 的結果影響位置 i+ji+j+1,最後轉成字串並去掉前導零。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def multiply(self, num1: str, num2: str) -> str:
m, n = len(num1), len(num2)
pos = [0] * (m + n)
for i in range(m - 1, -1, -1):
for j in range(n - 1, -1, -1):
mul = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0'))
p1, p2 = i + j, i + j + 1
total = mul + pos[p2]
pos[p1] += total // 10
pos[p2] = total % 10
res = ''.join(map(str, pos)).lstrip('0')
return res or '0'

46. Permutations

日期: 2025/01/03 | 難度: Medium | 分類: 回溯

題目說明

給一個不含重複數字的陣列,回傳所有排列。

解題邏輯

回溯:每次從未使用的數中選一個加入路徑,長度等於 nums 時記錄,用 used 標記已選的數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
def f(path, used):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
if used[i]:
continue
used[i] = True
path.append(nums[i])
f(path, used)
path.pop()
used[i] = False
f([], [False] * len(nums))
return res

47. Permutations II

日期: 2025/01/04 | 難度: Medium | 分類: 回溯

題目說明

陣列含重複數字,回傳所有不重複的排列。

解題邏輯

先排序,回溯時跳過重複條件:同一層若前一個相同的數沒被使用過,則跳過(避免同層重複選)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
used = [False] * len(nums)
def f(path):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
if used[i]:
continue
if i > 0 and nums[i] == nums[i - 1] and not used[i - 1]:
continue
used[i] = True
path.append(nums[i])
f(path)
path.pop()
used[i] = False
f([])
return res

53. Maximum Subarray

日期: 2024/12/16 | 難度: Medium | 分類: 動態規劃(Kadane’s)

題目說明

找出連續子陣列的最大和。

解題邏輯

Kadane’s Algorithm:若當前累積和 p > 0,繼續累加;否則從當前元素重新開始。

1
2
3
4
5
6
7
8
9
10
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
m = p = nums[0]
for i in nums[1:]:
if p > 0:
p += i
else:
p = i
m = max(p, m)
return m

54. Spiral Matrix

日期: 2024/12/29 | 難度: Medium | 分類: 陣列、模擬

題目說明

給一個 m×n 矩陣,以螺旋順序回傳所有元素。

解題邏輯

維護四個邊界(上下左右),每次沿著邊界走一圈,走完後將對應邊界收縮,直到所有元素都被走過。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
res = []
top, bottom, left, right = 0, len(matrix) - 1, 0, len(matrix[0]) - 1
while top <= bottom and left <= right:
for i in range(left, right + 1):
res.append(matrix[top][i])
top += 1
for i in range(top, bottom + 1):
res.append(matrix[i][right])
right -= 1
if top <= bottom:
for i in range(right, left - 1, -1):
res.append(matrix[bottom][i])
bottom -= 1
if left <= right:
for i in range(bottom, top - 1, -1):
res.append(matrix[i][left])
left += 1
return res

55. Jump Game

日期: 2024/12/25 | 難度: Medium | 分類: 貪心

題目說明

給一個陣列,nums[i] 表示在位置 i 最多能跳幾步,判斷能否跳到最後一格。

解題邏輯

貪心:維護目前能到達的最遠距離 reach,遍歷時若當前位置超過 reach 就無法到達,否則更新 reach。

1
2
3
4
5
6
7
8
class Solution:
def canJump(self, nums: List[int]) -> bool:
reach = 0
for i in range(len(nums)):
if i > reach:
return False
reach = max(reach, i + nums[i])
return True

59. Spiral Matrix II

日期: 2025/01/21 | 難度: Medium | 分類: 陣列、模擬

題目說明

給 n,生成一個按螺旋順序填入 1 到 n² 的 n×n 矩陣。

解題邏輯

同 54 的螺旋走法,但改為填數而非讀數,維護四個邊界依序填入遞增數字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
mat = [[0] * n for _ in range(n)]
top, bottom, left, right = 0, n - 1, 0, n - 1
num = 1
while top <= bottom and left <= right:
for i in range(left, right + 1):
mat[top][i] = num; num += 1
top += 1
for i in range(top, bottom + 1):
mat[i][right] = num; num += 1
right -= 1
if top <= bottom:
for i in range(right, left - 1, -1):
mat[bottom][i] = num; num += 1
bottom -= 1
if left <= right:
for i in range(bottom, top - 1, -1):
mat[i][left] = num; num += 1
left += 1
return mat

62. Unique Paths

日期: 2025/01/05 | 難度: Medium | 分類: 動態規劃

題目說明

機器人從 m×n 網格左上角走到右下角,只能向右或向下,共有幾條路徑?

解題邏輯

DP:dp[i][j] = dp[i-1][j] + dp[i][j-1],第一行和第一列都只有一條路。

1
2
3
4
5
6
7
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[1] * n for _ in range(m)]
for i in range(1, m):
for j in range(1, n):
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]

63. Unique Paths II

日期: 2025/01/15 | 難度: Medium | 分類: 動態規劃

題目說明

同 62,但格子中有障礙物(值為 1),無法通過障礙物。

解題邏輯

同 62 的 DP,遇到障礙物則該格路徑數為 0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m, n = len(obstacleGrid), len(obstacleGrid[0])
dp = [[0] * n for _ in range(m)]
for i in range(m):
if obstacleGrid[i][0] == 1:
break
dp[i][0] = 1
for j in range(n):
if obstacleGrid[0][j] == 1:
break
dp[0][j] = 1
for i in range(1, m):
for j in range(1, n):
if obstacleGrid[i][j] == 0:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]

67. Add Binary

日期: 2024/12/22 | 難度: Easy | 分類: 字串、數學

題目說明

給兩個二進位字串 ab,回傳它們的二進位和(字串形式)。

解題邏輯

將二進位字串轉整數相加,再轉回二進位字串(去掉 0b 前綴)。

1
2
3
class Solution:
def addBinary(self, a: str, b: str) -> str:
return bin(int(a, 2) + int(b, 2))[2:]

70. Climbing Stairs

日期: 2024/12/17 | 難度: Easy | 分類: 動態規劃、費波那契

題目說明

每次走 1 步或 2 步,爬 n 階有幾種方法?

解題邏輯

費波那契數列滾動更新,f(n) = f(n-1) + f(n-2)

1
2
3
4
5
6
7
8
9
10
class Solution:
def climbStairs(self, n: int) -> int:
to = 1
ans = t = 2
if n == 1:
return 1
for i in range(3, n + 1):
ans = t + to
to, t = t, ans
return ans

73. Set Matrix Zeroes

日期: 2024/12/29 | 難度: Medium | 分類: 陣列、矩陣

題目說明

若矩陣中某元素為 0,則將其整行和整列都設為 0,原地修改。

解題邏輯

先轉置取得各列,再遍歷每行判斷是否有 0,若有則整行為零;對每格再判斷其所在列是否有 0,若有則設為 0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
l = []
lst = [list(i) for i in zip(*matrix)]
for i in range(len(matrix)):
if matrix[i].count(0) == 0:
n = []
for j in range(len(matrix[i])):
if lst[j].count(0) == 0:
n.append(matrix[i][j])
else:
n.append(0)
l.append(n)
else:
l.append([0] * len(matrix[i]))
matrix[:] = l[:]

75. Sort Colors

日期: 2025/01/21 | 難度: Medium | 分類: 雙指針、排序

題目說明

給只含 0、1、2 的陣列,原地排序(荷蘭旗問題)。

解題邏輯

使用三個計數指針 n0n1n2:遇到 0 時,把 2 放 n2、1 放 n1、0 放 n0,三個指針都推進;遇到 1 時放 n1 和 n2;遇到 2 只放 n2。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def sortColors(self, nums: List[int]) -> None:
n0 = n1 = n2 = 0
for i in range(len(nums)):
if nums[i] == 0:
nums[n2] = 2
nums[n1] = 1
nums[n0] = 0
n2 += 1; n1 += 1; n0 += 1
elif nums[i] == 1:
nums[n2] = 2
nums[n1] = 1
n1 += 1; n2 += 1
else:
nums[n2] = 2
n2 += 1

77. Combinations

日期: 2024/12/30 | 難度: Medium | 分類: 回溯

題目說明

給整數 n 和 k,回傳 1 到 n 中所有 k 個數的組合。

解題邏輯

回溯:從 j 開始選數,選夠 k 個就記錄,每次選完往後遞迴避免重複。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
l = []
def f(j=1, num=[]):
if len(num) == k:
return l.append(num[:])
for i in range(j, n + 1):
num.append(i)
f(i + 1, num)
num.pop()
f()
return l

78. Subsets

日期: 2024/12/30 | 難度: Medium | 分類: 回溯

題目說明

給一個不重複整數陣列,回傳所有可能的子集(冪集)。

解題邏輯

DFS 回溯:每個節點都是一個子集(包含空集),每次從 j 開始選,防止重複。

1
2
3
4
5
6
7
8
9
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
def dfs(j, l):
lst.append(l)
for i in range(j, len(nums)):
dfs(i + 1, l + [nums[i]])
lst = []
dfs(0, [])
return lst

88. Merge Sorted Array

日期: 2024/12/20 | 難度: Easy | 分類: 陣列、雙指針

題目說明

將兩個已排序陣列 nums2 合併入 nums1(原地),nums1 後段有 n 個空位。

解題邏輯 — 方法一(簡單排序)

把 nums2 貼到 nums1 後段再排序。

1
2
3
4
class Solution:
def merge(self, nums1, m, nums2, n):
nums1[m:] = nums2[:]
nums1.sort()

解題邏輯 — 方法二(從尾端合併,O(m+n))

從兩陣列尾端開始比較,每次將較大的值填入 nums1 的末端,逐步向前,避免覆蓋未處理的元素。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def merge(self, nums1, m, nums2, n):
i = len(nums1) - 1
while n > 0:
if m > 0 and nums1[m - 1] > nums2[n - 1]:
nums1[i] = nums1[m - 1]
m -= 1
else:
nums1[i] = nums2[n - 1]
n -= 1
i -= 1
return nums1

90. Subsets II

日期: 2025/01/15 | 難度: Medium | 分類: 回溯

題目說明

陣列含重複數字,回傳所有不重複的子集。

解題邏輯

先排序,回溯時跳過同層重複的元素(j < i and nums[i] == nums[i-1]),確保不生成重複子集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
l = []
path = []
def f(j):
l.append(path[:])
for i in range(j, len(nums)):
if j < i and nums[i] == nums[i - 1]:
continue
path.append(nums[i])
f(i + 1)
path.pop()
f(0)
return l

91. Decode Ways

日期: 2025/01/04 | 難度: Medium | 分類: 動態規劃

題目說明

數字字串可映射到字母(1=A,…,26=Z),求有幾種解碼方式。

解題邏輯

DP:dp[i] 表示前 i 個字元的解碼方式數。若第 i 個字元不為 0,可由 dp[i-1] 轉來;若前兩個字元組成 10-26,可由 dp[i-2] 轉來。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def numDecodings(self, s: str) -> int:
n = len(s)
if n == 0 or s[0] == "0":
return 0
dp = [0] * (n + 1)
dp[0] = dp[1] = 1
for i in range(2, n + 1):
if s[i - 1] != "0":
dp[i] += dp[i - 1]
if s[i - 2] == "1" or s[i - 2] == "2" and s[i - 1] <= "6":
dp[i] += dp[i - 2]
return dp[-1]

100. Same Tree

日期: 2025/01/07 | 難度: Easy | 分類: 樹、遞迴

題目說明

判斷兩棵二元樹是否完全相同(結構和值都相同)。

解題邏輯

遞迴:兩節點都為空則 True;一個為空則 False;值不同則 False;否則遞迴比較左右子樹。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def isSameTree(self, p, q):
def f(p, q):
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return f(p.left, q.left) and f(p.right, q.right)
return f(p, q)

101. Symmetric Tree

日期: 2025/01/07 | 難度: Easy | 分類: 樹、BFS

題目說明

判斷一棵二元樹是否為左右對稱(鏡像樹)。

解題邏輯 — 方法一(BFS 配對)

用 queue 存配對節點 (t1, t2),每次取出比較,並將 (t1.left, t2.right)(t1.right, t2.left) 加入 queue。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def isSymmetric(self, root):
if not root:
return True
queue = [(root.left, root.right)]
while queue:
t1, t2 = queue.pop(0)
if not t1 and not t2:
continue
if not t1 or not t2 or t1.val != t2.val:
return False
queue.append((t1.left, t2.right))
queue.append((t1.right, t2.left))
return True

解題邏輯 — 方法二(逐層比較)

BFS 逐層取出節點值(包含 None),若每層的值列表不是回文則不對稱。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def isSymmetric(self, root):
if not root:
return True
q = [root]
while q:
n = len(q)
l = []
for i in range(n):
r = q.pop(0)
if r:
l.append(r.val)
q.append(r.left)
q.append(r.right)
else:
l.append(None)
if l != l[::-1]:
return False
return True

102. Binary Tree Level Order Traversal

日期: 2025/01/14 | 難度: Medium | 分類: 樹、BFS

題目說明

回傳二元樹的逐層遍歷結果(每層為一個列表)。

解題邏輯

BFS:用 queue 進行層序遍歷,每次處理同一層的所有節點並加入 level 列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def levelOrder(self, root):
if not root:
return []
q = [root]
l = []
while q:
level = []
for i in range(len(q)):
node = q.pop(0)
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
l.append(level)
return l

104. Maximum Depth of Binary Tree

日期: 2025/01/07 | 難度: Easy | 分類: 樹、遞迴

題目說明

求二元樹的最大深度(根到最遠葉節點的節點數)。

解題邏輯

遞迴:每個節點的深度 = max(左子樹深度, 右子樹深度) + 1,空節點深度為 0。

1
2
3
4
5
6
7
class Solution:
def maxDepth(self, root):
def f(root):
if not root:
return 0
return max(f(root.right) + 1, f(root.left) + 1)
return f(root)

107. Binary Tree Level Order Traversal II

日期: 2025/01/14 | 難度: Medium | 分類: 樹、BFS

題目說明

從下往上的層序遍歷(最底層先,根層最後)。

解題邏輯

與 102 相同的 BFS,但最後將結果列表反轉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from collections import deque
class Solution:
def levelOrderBottom(self, root):
if not root:
return []
q = deque([root])
l = []
while q:
level = []
for i in range(len(q)):
node = q.popleft()
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
l.append(level)
return l[::-1]

111. Minimum Depth of Binary Tree

日期: 2025/01/07 | 難度: Easy | 分類: 樹、遞迴

題目說明

求二元樹的最小深度(根到最近葉節點的節點數)。

解題邏輯

遞迴,但需注意:若某節點只有一個子節點,不能取兩者的 min(另一邊是 0),要選有子節點的那側。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def minDepth(self, root):
def f(root):
if not root:
return 0
if not root.left:
return f(root.right) + 1
if not root.right:
return f(root.left) + 1
return min(f(root.left), f(root.right)) + 1
return f(root)

112. Path Sum

日期: 2025/01/08 | 難度: Easy | 分類: 樹、遞迴

題目說明

判斷是否存在從根到葉節點的路徑,使路徑上所有節點值之和等於 targetSum。

解題邏輯

遞迴:累加節點值,到達葉節點時判斷是否等於 targetSum。

1
2
3
4
5
6
7
8
9
10
class Solution:
def hasPathSum(self, root, targetSum):
def f(root, s):
if not root:
return False
s += root.val
if not root.left and not root.right:
return s == targetSum
return f(root.right, s) or f(root.left, s)
return f(root, 0)

118. Pascal’s Triangle

日期: 2024/12/22 | 難度: Easy | 分類: 動態規劃、陣列

題目說明

生成前 numRows 行的楊輝三角。

解題邏輯

先建立每行為全 1 的陣列,再從第三行開始更新中間元素 c[i][j] = c[i-1][j-1] + c[i-1][j]

1
2
3
4
5
6
7
class Solution:
def generate(self, numRows: int) -> List[List[int]]:
c = [[1] * (i + 1) for i in range(numRows)]
for i in range(2, numRows):
for j in range(1, i):
c[i][j] = c[i - 1][j - 1] + c[i - 1][j]
return c

119. Pascal’s Triangle II

難度: Easy | 分類: 動態規劃

題目說明

只回傳楊輝三角第 rowIndex 行(0-indexed)。

解題邏輯

[1] 開始,每次在尾端加 0,然後從後往前更新 row[j] += row[j-1],等同於在同一個陣列上模擬楊輝三角的生成。

1
2
3
4
5
6
7
8
class Solution:
def getRow(self, rowIndex: int) -> list[int]:
row = [1]
for i in range(rowIndex):
row.append(0)
for j in range(len(row) - 1, 0, -1):
row[j] += row[j - 1]
return row

121. Best Time to Buy and Sell Stock

日期: 2024/12/16 | 難度: Easy | 分類: 貪心、動態規劃

題目說明

只能買賣一次,求最大利潤。

解題邏輯

一次遍歷:維護最低買入價 mn 和最大利潤 dp,每天更新兩者。

1
2
3
4
5
6
7
8
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp = float(-inf)
mn = float(inf)
for i in prices:
mn = min(i, mn)
dp = max(dp, i - mn)
return dp

122. Best Time to Buy and Sell Stock II

日期: 2025/01/15 | 難度: Medium | 分類: 貪心

題目說明

可以多次買賣,但同一時間只能持有一股,求最大利潤。

解題邏輯

貪心:只要今天比昨天高,就把差價(利潤)加進來。等同於在每個上升段都賺到差價。

1
2
3
4
5
6
7
8
9
class Solution:
def maxProfit(self, prices: List[int]) -> int:
io = prices[0]
n = 0
for i in prices[1:]:
if i > io:
n += i - io
io = i
return n

136. Single Number

日期: 2024/12/17 | 難度: Easy | 分類: 位元運算

題目說明

每個元素出現兩次,只有一個出現一次,找出它。

解題邏輯

XOR:相同的數 XOR 為 0,所有數 XOR 後剩下的就是只出現一次的數。

1
2
3
4
5
6
class Solution:
def singleNumber(self, nums: List[int]) -> int:
x = 0
for i in nums:
x ^= i
return x

137. Single Number II

日期: 2024/12/17 | 難度: Medium | 分類: 位元運算

題目說明

每個元素出現三次,只有一個出現一次,用 O(1) 空間找出它。

解題邏輯

用兩個位元遮罩 xy 模擬三進制計數,出現三次的數會被清零,剩下 x 就是答案。

1
2
3
4
5
6
7
class Solution:
def singleNumber(self, nums: List[int]) -> int:
x = y = 0
for i in nums:
x = x ^ i & ~y
y = y ^ i & ~x
return x

150. Evaluate Reverse Polish Notation

日期: 2024/12/18 | 難度: Medium | 分類: Stack

題目說明

計算逆波蘭表達式(後綴表達式)。

解題邏輯

Stack:遇數字 push;遇運算子 pop 兩個數計算後 push 結果。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
l = []
for i in tokens:
if i in ['+', '-', '*', '/']:
b = l.pop()
a = l.pop()
l.append(int(eval(str(a) + i + str(b))))
else:
l.append(int(i))
return int(l[0])

151. Reverse Words in a String

日期: 2025/01/24 | 難度: Medium | 分類: 字串

題目說明

反轉字串中的單字順序,去除多餘空白。

解題邏輯

split() 自動分割並去除多餘空白,然後反轉列表再用空格連接。

1
2
3
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join(s.split()[::-1])

168. Excel Sheet Column Title

日期: 2025/01/02 | 難度: Easy | 分類: 數學

題目說明

給一個整數 n,回傳對應 Excel 欄位標題(1→A, 26→Z, 27→AA…)。

解題邏輯

類似 26 進位,但沒有 0(A=1, Z=26),每次取 (n-1) % 26 得字母,再將 n = (n-1) // 26

1
2
3
4
5
6
7
8
class Solution:
def convertToTitle(self, columnNumber: int) -> str:
res = ''
while columnNumber:
columnNumber -= 1
res = chr(columnNumber % 26 + ord('A')) + res
columnNumber //= 26
return res

189. Rotate Array

日期: 2024/12/15 | 難度: Medium | 分類: 陣列

題目說明

將陣列向右旋轉 k 步。

解題邏輯

Python 切片:取後 k 個接前面部分,k %= len(nums) 避免超出範圍。

1
2
3
4
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
k %= len(nums)
nums[:] = nums[-k:] + nums[:-k]

198. House Robber

日期: 2024/12/24 | 難度: Medium | 分類: 動態規劃

題目說明

不能搶相鄰房子,求能搶到的最大金額。

解題邏輯

DP:dp[i] = max(dp[i-1], dp[i-2] + nums[i]),用兩個變數滾動代替陣列。

1
2
3
4
5
6
class Solution:
def rob(self, nums: List[int]) -> int:
prev2 = prev1 = 0
for n in nums:
prev2, prev1 = prev1, max(prev1, prev2 + n)
return prev1

202. Happy Number

日期: 2024/12/23 | 難度: Easy | 分類: 數學、雜湊集合

題目說明

對一個數,反覆將各位數字的平方和替換,最終若能到 1 則為「快樂數」。

解題邏輯

用集合記錄見過的數,若重複出現代表進入循環(不是快樂數),若到 1 則是。

1
2
3
4
5
6
7
8
9
class Solution:
def isHappy(self, n: int) -> bool:
seen = set()
while n != 1:
if n in seen:
return False
seen.add(n)
n = sum(int(d) ** 2 for d in str(n))
return True

205. Isomorphic Strings

日期: 2024/12/24 | 難度: Easy | 分類: 字串、雜湊表

題目說明

判斷兩個字串是否同構(可以通過一對一的字元映射使 s 變成 t)。

解題邏輯

建立兩個方向的映射字典,確保 s→t 和 t→s 的映射都是一對一的。

1
2
3
4
5
6
7
8
9
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
d1, d2 = {}, {}
for a, b in zip(s, t):
if d1.get(a, b) != b or d2.get(b, a) != a:
return False
d1[a] = b
d2[b] = a
return True

209. Minimum Size Subarray Sum

日期: 2025/01/21 | 難度: Medium | 分類: 滑動視窗

題目說明

找和 ≥ target 的最短連續子陣列長度。

解題邏輯

滑動視窗:右指針 i 擴張累加,當 s >= target 時記錄長度並從左收縮,持續更新最小長度。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
j = 0
s = 0
min_len = float('inf')
for i in range(len(nums)):
s += nums[i]
while s >= target:
min_len = min(min_len, i - j + 1)
s -= nums[j]
j += 1
return 0 if min_len == float('inf') else min_len

213. House Robber II

日期: 2024/12/25 | 難度: Medium | 分類: 動態規劃

題目說明

房子排成環狀(首尾相鄰),不能搶相鄰房子,求最大金額。

解題邏輯

環狀問題拆成兩個線性問題:搶 nums[0..n-2] 或搶 nums[1..n-1],取兩者最大值。每個子問題用 House Robber I 的 DP 解。

1
2
3
4
5
6
7
8
9
10
class Solution:
def rob(self, nums: List[int]) -> int:
def robLine(arr):
prev2 = prev1 = 0
for n in arr:
prev2, prev1 = prev1, max(prev1, prev2 + n)
return prev1
if len(nums) == 1:
return nums[0]
return max(robLine(nums[:-1]), robLine(nums[1:]))

216. Combination Sum III

日期: 2025/01/04 | 難度: Medium | 分類: 回溯

題目說明

從 1-9 中選 k 個不重複的數,使其和為 n,找所有組合。

解題邏輯

回溯:從當前數開始選,選夠 k 個且和為 n 時記錄,超出則剪枝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
res = []
def f(start, path, remain):
if len(path) == k and remain == 0:
res.append(path[:])
return
for i in range(start, 10):
if i > remain:
break
path.append(i)
f(i + 1, path, remain - i)
path.pop()
f(1, [], n)
return res

219. Contains Duplicate II

日期: 2024/12/27 | 難度: Easy | 分類: 雜湊表、滑動視窗

題目說明

判斷陣列中是否存在兩個相同的數,且它們的索引差 ≤ k。

解題邏輯

用字典記錄每個數最後出現的索引,若同一個數再次出現且索引差 ≤ k 則回傳 True。

1
2
3
4
5
6
7
8
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
d = {}
for i, n in enumerate(nums):
if n in d and i - d[n] <= k:
return True
d[n] = i
return False

224. Basic Calculator

日期: 2024/12/18 | 難度: Hard | 分類: Stack、字串解析

題目說明

計算含 +-、括號的運算式字串。

解題邏輯 — 方法一(Shunting Yard)

轉換中綴為 RPN 再計算,負號在開頭或括號後補 0- 處理。

解題邏輯 — 方法二(符號追蹤,精簡版)

Stack 存外層符號方向,括號改變符號環境,每遇到數字就乘上當前符號方向加入結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution:
def calculate(self, s: str) -> int:
sign = 1
stack = [sign]
num = 0
res = 0
s += ' '
for i in s:
if i.isdigit():
num = 10 * num + int(i)
else:
res += sign * num
num = 0
if i == '+':
sign = stack[-1]
elif i == '-':
sign = -stack[-1]
elif i == '(':
stack.append(sign)
elif i == ')':
stack.pop()
return res

226. Invert Binary Tree

日期: 2025/01/13 | 難度: Easy | 分類: 樹、遞迴

題目說明

翻轉一棵二元樹(左右子樹互換)。

解題邏輯

遞迴:交換左右子節點,再遞迴翻轉兩個子樹。

1
2
3
4
5
6
7
8
class Solution:
def invertTree(self, root):
if not root:
return None
root.left, root.right = root.right, root.left
self.invertTree(root.left)
self.invertTree(root.right)
return root

227. Basic Calculator II

日期: 2024/12/18 | 難度: Medium | 分類: Stack

題目說明

計算含 +-*/ 的運算式(無括號)。

解題邏輯 — 方法一(Shunting Yard)

轉 RPN 後求值,利用優先級字典控制 pop 時機。

解題邏輯 — 方法二(Stack 直接計算)

用上一個運算子 t 決定當前數的處理方式:+/- 直接 push 正負數,*// 則 pop 上一個數計算後再 push,最後 sum(stack)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
def calculate(self, s: str) -> int:
l = []
n = ''
t = '+'
s += '+'
for i in s:
if i == " ":
continue
if i.isdigit():
n += i
else:
n = int(n)
if t == "+":
l.append(n)
elif t == "-":
l.append(-n)
elif t == "*":
l.append(l.pop() * n)
elif t == "/":
l.append(int(l.pop() / n))
t = i
n = ''
return sum(l)

240. Search a 2D Matrix II

日期: 2025/01/24 | 難度: Medium | 分類: 二分搜尋、矩陣

題目說明

在每行從左到右、每列從上到下已排序的矩陣中搜尋目標值。

解題邏輯

從右上角開始:若當前值 > target 則左移(列–),若 < target 則下移(行++),直到找到或越界。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def searchMatrix(self, matrix, target):
r, c = 0, len(matrix[0]) - 1
while r < len(matrix) and c >= 0:
if matrix[r][c] == target:
return True
elif matrix[r][c] > target:
c -= 1
else:
r += 1
return False

242. Valid Anagram

日期: 2024/12/17 | 難度: Easy | 分類: 字串、雜湊表

題目說明

判斷 t 是否為 s 的字母異位詞。

解題邏輯

Counter 統計字母頻次,比較兩個 Counter 是否相等。

1
2
3
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
return Counter(s) == Counter(t)

257. Binary Tree Paths

日期: 2025/01/09 | 難度: Easy | 分類: 樹、DFS、回溯

題目說明

回傳二元樹從根到所有葉節點的路徑(字串格式如 “1->2->5”)。

解題邏輯

DFS:遞迴向下走,到達葉節點時將路徑加入結果,路徑用 -> 連接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def binaryTreePaths(self, root):
res = []
def dfs(node, path):
if not node:
return
path += str(node.val)
if not node.left and not node.right:
res.append(path)
else:
dfs(node.left, path + '->')
dfs(node.right, path + '->')
dfs(root, '')
return res

263. Ugly Number

日期: 2025/01/03 | 難度: Easy | 分類: 數學

題目說明

醜數是只含質因數 2、3、5 的正整數,判斷 n 是否為醜數。

解題邏輯

不斷整除 2、3、5,最後若等於 1 則是醜數。

1
2
3
4
5
6
7
8
class Solution:
def isUgly(self, n: int) -> bool:
if n <= 0:
return False
for p in [2, 3, 5]:
while n % p == 0:
n //= p
return n == 1

283. Move Zeroes

日期: 2024/12/16 | 難度: Easy | 分類: 陣列

題目說明

原地將所有 0 移到末尾,保持非零元素相對順序。

解題邏輯

計算 0 的個數,反覆執行「移除第一個 0 → 末尾補 0」。

1
2
3
4
5
6
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
c = nums.count(0)
for i in range(c):
nums.remove(0)
nums.append(0)

290. Word Pattern

日期: 2024/12/28 | 難度: Easy | 分類: 字串、雜湊表

題目說明

判斷 pattern 和 s 是否遵循相同的模式(字母對單字,一對一映射)。

解題邏輯

建立雙向映射(字母→單字、單字→字母),確保兩側都是一對一。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def wordPattern(self, pattern: str, s: str) -> bool:
words = s.split()
if len(pattern) != len(words):
return False
d1, d2 = {}, {}
for p, w in zip(pattern, words):
if d1.get(p, w) != w or d2.get(w, p) != p:
return False
d1[p] = w
d2[w] = p
return True

300. Longest Increasing Subsequence

日期: 2025/01/05 | 難度: Medium | 分類: 動態規劃

題目說明

找出最長嚴格遞增子序列的長度。

解題邏輯

DP:dp[i] = 以 nums[i] 結尾的最長遞增子序列長度,對每個 i 往前找所有 j < inums[j] < nums[i] 的 dp[j]+1 取最大。

1
2
3
4
5
6
7
8
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = [1] * len(nums)
for i in range(1, len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)

322. Coin Change

日期: 2025/01/24 | 難度: Medium | 分類: 動態規劃

題目說明

給硬幣面額陣列和目標金額,求湊成 amount 所需的最少硬幣數,無法湊成回傳 -1。

解題邏輯

Bottom-up DP:dp[i] = 湊成金額 i 的最少硬幣數。對每個金額,嘗試所有硬幣,dp[i] = min(dp[i], dp[i-c]+1)

1
2
3
4
5
6
7
8
9
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for c in coins:
if c <= i:
dp[i] = min(dp[i], dp[i - c] + 1)
return dp[amount] if dp[amount] != float('inf') else -1

334. Increasing Triplet Subsequence

日期: 2025/02/03 | 難度: Medium | 分類: 貪心

題目說明

判斷是否存在長度為 3 的遞增子序列。

解題邏輯

貪心:維護兩個變數 first(最小值)和 second(在 first 之後的次小值),若遇到比 second 大的數則找到三元組。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def increasingTriplet(self, nums: List[int]) -> bool:
first = second = float('inf')
for n in nums:
if n <= first:
first = n
elif n <= second:
second = n
else:
return True
return False

338. Counting Bits

日期: 2025/01/02 | 難度: Easy | 分類: 動態規劃、位元運算

題目說明

給 n,回傳 0 到 n 每個數的二進位表示中 1 的個數。

解題邏輯

DP:dp[i] = dp[i >> 1] + (i & 1)(右移一位去掉最低位,加上最低位是否為 1)。

1
2
3
4
5
6
class Solution:
def countBits(self, n: int) -> List[int]:
dp = [0] * (n + 1)
for i in range(1, n + 1):
dp[i] = dp[i >> 1] + (i & 1)
return dp

342. Power of Four

日期: 2025/01/02 | 難度: Easy | 分類: 數學、位元運算

題目說明

判斷 n 是否為 4 的冪次方。

解題邏輯

4 的冪次方同時是 2 的冪次方(n & (n-1) == 0),且其二進位的 1 只出現在奇數位(用 0x55555555 遮罩驗證)。

1
2
3
class Solution:
def isPowerOfFour(self, n: int) -> bool:
return n > 0 and (n & (n - 1)) == 0 and (n & 0x55555555) != 0

344. Reverse String

日期: 2024/12/23 | 難度: Easy | 分類: 雙指針、字串

題目說明

原地反轉字元陣列。

解題邏輯

雙指針從兩端向中間交換,或直接用切片賦值。

1
2
3
class Solution:
def reverseString(self, s: List[str]) -> None:
s[:] = s[::-1]

345. Reverse Vowels of a String

日期: 2025/02/03 | 難度: Easy | 分類: 雙指針、字串

題目說明

只反轉字串中的母音字母,其他字母位置不變。

解題邏輯

雙指針:左右指針向中間靠,都指到母音時交換,否則對應移動指針。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def reverseVowels(self, s: str) -> str:
vowels = set('aeiouAEIOU')
s = list(s)
l, r = 0, len(s) - 1
while l < r:
while l < r and s[l] not in vowels:
l += 1
while l < r and s[r] not in vowels:
r -= 1
s[l], s[r] = s[r], s[l]
l += 1; r -= 1
return ''.join(s)

350. Intersection of Two Arrays II

日期: 2024/12/15 | 難度: Easy | 分類: 雜湊表

題目說明

找兩個陣列的交集(含重複元素),每個元素出現次數取兩者最小值。

解題邏輯

找共同元素集合,每個元素按 min(count1, count2) 次加入結果。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def intersect(self, nums1, nums2):
s = set()
for i in nums1:
if i in nums2:
s.add(i)
l = []
for i in s:
c = min(nums1.count(i), nums2.count(i))
for j in range(c):
l.append(i)
return l

371. Sum of Two Integers

日期: 2024/12/28 | 難度: Medium | 分類: 位元運算

題目說明

不使用 +-,計算兩個整數的和。

解題邏輯

用位元運算:XOR 得到不進位的和,AND 左移 1 位得到進位,反覆直到無進位。Python 需處理負數補碼(mask 限制位元數)。

1
2
3
4
5
6
7
8
class Solution:
def getSum(self, a: int, b: int) -> int:
mask = 0xFFFFFFFF
while b & mask:
carry = (a & b) << 1
a = a ^ b
b = carry
return (a & mask) if b > 0 else a

383. Ransom Note

日期: 2025/01/03 | 難度: Easy | 分類: 字串、雜湊表

題目說明

判斷是否可以用 magazine 中的字母拼出 ransomNote(每個字母只能用一次)。

解題邏輯

Counter 統計兩者字母頻次,ransomNote 的每個字母在 magazine 中都要有足夠數量。

1
2
3
4
5
6
7
8
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
d = Counter(magazine)
for c in ransomNote:
if d[c] <= 0:
return False
d[c] -= 1
return True

387. First Unique Character in a String

日期: 2024/12/23 | 難度: Easy | 分類: 字串、雜湊表

題目說明

找字串中第一個不重複字元的索引,不存在回傳 -1。

解題邏輯

Counter 統計頻次,再遍歷找第一個頻次為 1 的字元。

1
2
3
4
5
6
7
class Solution:
def firstUniqChar(self, s: str) -> int:
d = Counter(s)
for i, c in enumerate(s):
if d[c] == 1:
return i
return -1

389. Find the Difference

日期: 2024/12/17 | 難度: Easy | 分類: 字串、位元運算

題目說明

字串 t 是 s 打亂後多插入一個字母,找出多出的那個字母。

解題邏輯

將 t 所有字母的 ASCII 碼加總,減去 s 所有字母的 ASCII 碼,差值即為多出字母的 ASCII。

1
2
3
4
5
6
7
8
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
ans = 0
for i in t:
ans += ord(i)
for i in s:
ans -= ord(i)
return chr(ans)

392. Is Subsequence

日期: 2025/02/05 | 難度: Easy | 分類: 雙指針、字串

題目說明

判斷 s 是否為 t 的子序列(保持相對順序但不一定連續)。

解題邏輯

雙指針:i 指向 s,j 指向 t,遍歷 t,遇到 s[i] 時 i 前進,最終若 i == len(s) 則是子序列。

1
2
3
4
5
6
7
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
i = 0
for c in t:
if i < len(s) and c == s[i]:
i += 1
return i == len(s)

404. Sum of Left Leaves

日期: 2025/01/09 | 難度: Easy | 分類: 樹、遞迴

題目說明

計算二元樹所有左葉節點的值之和。

解題邏輯

遞迴:傳遞一個 is_left 標記,到達葉節點且 is_left=True 時加入結果。

1
2
3
4
5
6
7
8
9
class Solution:
def sumOfLeftLeaves(self, root):
def f(node, is_left):
if not node:
return 0
if not node.left and not node.right:
return node.val if is_left else 0
return f(node.left, True) + f(node.right, False)
return f(root, False)

405. Convert a Number to Hexadecimal

日期: 2025/01/02 | 難度: Easy | 分類: 位元運算、數學

題目說明

將整數轉換為十六進位字串,負數用補碼(二的補碼)表示。

解題邏輯

每次取最低 4 位(n & 0xf)轉成十六進位字元,再右移 4 位,重複 8 次(32 位)。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def toHex(self, num: int) -> str:
if num == 0:
return '0'
hex_chars = '0123456789abcdef'
res = ''
if num < 0:
num = num + 2**32
while num:
res = hex_chars[num & 0xf] + res
num >>= 4
return res

409. Longest Palindrome

日期: 2024/12/27 | 難度: Easy | 分類: 字串、雜湊表

題目說明

給一個字串,用其字母能組成的最長回文串長度。

解題邏輯

出現偶數次的字母全部可用,出現奇數次的字母可用奇數-1個,若有任何奇數次的字母還可以在中間多放一個。

1
2
3
4
5
6
7
8
9
10
class Solution:
def longestPalindrome(self, s: str) -> int:
d = Counter(s)
res = 0
odd = False
for v in d.values():
res += v if v % 2 == 0 else v - 1
if v % 2 == 1:
odd = True
return res + (1 if odd else 0)

435. Non-overlapping Intervals

日期: 2025/01/05 | 難度: Medium | 分類: 貪心、排序

題目說明

找最少需要移除幾個區間才能使剩餘區間互不重疊。

解題邏輯

貪心:按結束時間排序,盡量保留結束時間早的區間(貪心選擇),遇到重疊就計數移除。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key=lambda x: x[1])
count = 0
end = float('-inf')
for s, e in intervals:
if s >= end:
end = e
else:
count += 1
return count

437. Path Sum III

日期: 2025/02/24 | 難度: Medium | 分類: 樹、前綴和

題目說明

找二元樹中所有路徑(不須從根到葉)使路徑上節點值之和等於 targetSum,路徑方向只能向下。

解題邏輯

前綴和 + DFS:用字典記錄從根到當前節點的前綴和出現次數,每個節點檢查是否存在 prefix_sum - targetSum 在字典中,即可得到以當前節點結尾的合法路徑數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def pathSum(self, root, targetSum):
from collections import defaultdict
prefix = defaultdict(int)
prefix[0] = 1
res = [0]
def dfs(node, curr):
if not node:
return
curr += node.val
res[0] += prefix[curr - targetSum]
prefix[curr] += 1
dfs(node.left, curr)
dfs(node.right, curr)
prefix[curr] -= 1
dfs(root, 0)
return res[0]

443. String Compression

日期: 2025/02/03 | 難度: Medium | 分類: 字串、雙指針

題目說明

原地壓縮字元陣列:連續相同字元用「字元+次數」表示(次數為 1 時省略),回傳壓縮後長度。

解題邏輯

雙指針:i 掃描,w 寫入位置,統計連續相同字元的數量後寫入字元和數字(多位數分別寫入)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def compress(self, chars: List[str]) -> int:
w = 0
i = 0
while i < len(chars):
c = chars[i]
count = 0
while i < len(chars) and chars[i] == c:
i += 1
count += 1
chars[w] = c
w += 1
if count > 1:
for d in str(count):
chars[w] = d
w += 1
return w

448. Find All Numbers Disappeared in an Array

日期: 2024/12/27 | 難度: Easy | 分類: 陣列

題目說明

在長度為 n 的陣列(值在 1-n 之間),找出所有未出現的數。

解題邏輯

nums[abs(nums[i])-1] 標記為負數(表示該索引對應的值出現過),最後正數位置的索引+1 就是未出現的數。

1
2
3
4
5
6
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
for n in nums:
i = abs(n) - 1
nums[i] = -abs(nums[i])
return [i + 1 for i in range(len(nums)) if nums[i] > 0]

463. Island Perimeter

日期: 2024/12/28 | 難度: Easy | 分類: 陣列、矩陣

題目說明

給一個格狀地圖,1 代表陸地,0 代表水,計算島嶼的周長。

解題邏輯

每個陸地格貢獻 4 條邊,但相鄰的陸地格共享的邊不算,每對相鄰陸地減 2。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
res = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
res += 4
if i > 0 and grid[i-1][j] == 1:
res -= 2
if j > 0 and grid[i][j-1] == 1:
res -= 2
return res

476. Number Complement

日期: 2025/01/02 | 難度: Easy | 分類: 位元運算

題目說明

給一個正整數,回傳其補數(翻轉二進位所有位元)。

解題邏輯

建立一個與 num 位數相同的全 1 遮罩,用 XOR 翻轉所有位元。

1
2
3
4
class Solution:
def findComplement(self, num: int) -> int:
mask = (1 << num.bit_length()) - 1
return num ^ mask

494. Target Sum

日期: 2025/01/24 | 難度: Medium | 分類: 動態規劃、回溯

題目說明

對陣列每個數加 + 或 -,使其總和等於 target,求有幾種方式。

解題邏輯

DP(字典記錄可能的和及次數):從空開始,每次加入一個數,更新每種和的出現次數。

1
2
3
4
5
6
7
8
9
10
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
dp = {0: 1}
for n in nums:
new_dp = {}
for s, cnt in dp.items():
new_dp[s + n] = new_dp.get(s + n, 0) + cnt
new_dp[s - n] = new_dp.get(s - n, 0) + cnt
dp = new_dp
return dp.get(target, 0)

496. Next Greater Element I

日期: 2024/12/28 | 難度: Easy | 分類: Stack、單調堆疊

題目說明

給 nums1 和 nums2(nums1 是 nums2 的子集),對 nums1 的每個元素找在 nums2 中右側第一個更大的元素。

解題邏輯

單調遞減堆疊:遍歷 nums2,維護一個單調遞減的 stack,遇到比 stack 頂更大的數時,stack 頂的「下一個更大元素」就是當前數,記入字典。最後查 nums1 的元素。

1
2
3
4
5
6
7
8
9
class Solution:
def nextGreaterElement(self, nums1, nums2):
d = {}
stack = []
for n in nums2:
while stack and stack[-1] < n:
d[stack.pop()] = n
stack.append(n)
return [d.get(n, -1) for n in nums1]

500. Keyboard Row

日期: 2024/12/27 | 難度: Easy | 分類: 字串、雜湊表

題目說明

找出陣列中能用鍵盤同一行字母拼寫的單字。

解題邏輯

定義三行的字母集合,判斷每個單字的字母是否全在同一行中。

1
2
3
4
5
6
7
8
9
class Solution:
def findWords(self, words: List[str]) -> List[str]:
rows = [set('qwertyuiop'), set('asdfghjkl'), set('zxcvbnm')]
res = []
for w in words:
s = set(w.lower())
if any(s <= r for r in rows):
res.append(w)
return res

543. Diameter of Binary Tree

日期: 2025/01/13 | 難度: Easy | 分類: 樹、遞迴

題目說明

求二元樹的直徑(任意兩節點間最長路徑的邊數)。

解題邏輯

DFS:每個節點的直徑候選 = 左子樹深度 + 右子樹深度,遞迴過程中更新全域最大值。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def diameterOfBinaryTree(self, root):
self.ans = 0
def depth(node):
if not node:
return 0
l = depth(node.left)
r = depth(node.right)
self.ans = max(self.ans, l + r)
return max(l, r) + 1
depth(root)
return self.ans

556. Next Greater Element III

日期: 2024/12/28 | 難度: Medium | 分類: 數學、字串

題目說明

給一個整數 n,找出用 n 的各位數字重排後比 n 大的最小整數,不存在或超出 32 位範圍則回傳 -1。

解題邏輯

Next permutation 演算法:從右找第一個下降點 i,再從右找第一個比 digits[i] 大的數交換,最後反轉 i+1 之後的部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def nextGreaterElement(self, n: int) -> int:
digits = list(str(n))
i = len(digits) - 2
while i >= 0 and digits[i] >= digits[i + 1]:
i -= 1
if i < 0:
return -1
j = len(digits) - 1
while digits[j] <= digits[i]:
j -= 1
digits[i], digits[j] = digits[j], digits[i]
digits[i + 1:] = digits[i + 1:][::-1]
res = int(''.join(digits))
return res if res <= 2**31 - 1 else -1

561. Array Partition

日期: 2024/12/24 | 難度: Easy | 分類: 陣列、排序

題目說明

把 2n 個整數兩兩配對,使所有對的最小值之和最大。

解題邏輯

排序後取奇數索引(0,2,4…)的元素之和,因為排序後相鄰配對使小值最大化。

1
2
3
4
class Solution:
def arrayPairSum(self, nums: List[int]) -> int:
nums.sort()
return sum(nums[::2])

572. Subtree of Another Tree

日期: 2025/01/13 | 難度: Easy | 分類: 樹、遞迴

題目說明

判斷 subRoot 是否為 root 的子樹。

解題邏輯

對 root 的每個節點,判斷以該節點為根的子樹是否與 subRoot 相同(用 isSameTree 的邏輯),遞迴檢查左右子樹。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def isSubtree(self, root, subRoot):
def same(a, b):
if not a and not b:
return True
if not a or not b or a.val != b.val:
return False
return same(a.left, b.left) and same(a.right, b.right)
if not root:
return False
if same(root, subRoot):
return True
return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)

575. Distribute Candies

日期: 2024/12/26 | 難度: Easy | 分類: 雜湊集合

題目說明

Alice 有 n 顆糖(n 為偶數),要分一半給哥哥,她想要儘量多種類,求她能得到的最多種類數。

解題邏輯

種類數 = min(不同糖的種類數, n//2),用 set 去重取種類數。

1
2
3
class Solution:
def distributeCandies(self, candyType: List[int]) -> int:
return min(len(set(candyType)), len(candyType) // 2)

581. Shortest Unsorted Continuous Subarray

日期: 2025/01/05 | 難度: Medium | 分類: 陣列、排序

題目說明

找出最短的連續子陣列,使排序後整個陣列有序。

解題邏輯

比較原陣列和排序後的陣列,找出第一個和最後一個不同的位置,兩者之間的長度就是答案。

1
2
3
4
5
6
7
8
9
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
sorted_nums = sorted(nums)
l, r = 0, len(nums) - 1
while l <= r and nums[l] == sorted_nums[l]:
l += 1
while r >= l and nums[r] == sorted_nums[r]:
r -= 1
return r - l + 1 if l <= r else 0

637. Average of Levels in Binary Tree

日期: 2025/01/13 | 難度: Easy | 分類: 樹、BFS

題目說明

回傳二元樹每層節點的平均值。

解題邏輯

BFS 層序遍歷,每層計算平均值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def averageOfLevels(self, root):
res = []
q = [root]
while q:
level = []
for _ in range(len(q)):
node = q.pop(0)
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
res.append(sum(level) / len(level))
return res

643. Maximum Average Subarray I

日期: 2025/02/05 | 難度: Easy | 分類: 滑動視窗

題目說明

找長度為 k 的連續子陣列的最大平均值。

解題邏輯

固定大小的滑動視窗:先計算前 k 個元素的和,然後逐步移動視窗(加新去舊),維護最大和。

1
2
3
4
5
6
7
8
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
w = sum(nums[:k])
m = w
for i in range(k, len(nums)):
w += nums[i] - nums[i - k]
m = max(m, w)
return m / k

日期: 2024/12/20 | 難度: Easy | 分類: 二分搜尋

題目說明

在已排序陣列中找目標值的索引,找不到回傳 -1。

解題邏輯

標準二分搜尋:維護左右邊界,每次取中點比較縮小範圍。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def search(self, nums: List[int], target: int) -> int:
r = len(nums) - 1
left = 0
while r >= left:
mid = (r + left) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
r = mid - 1
else:
return mid
return -1

724. Find Pivot Index

日期: 2024/12/20 | 難度: Easy | 分類: 前綴和

題目說明

找樞紐索引:左側所有元素之和等於右側所有元素之和。

解題邏輯

n 從總和開始每次扣當前元素(= 右側和),s 累積(= 左側和),相等時找到樞紐。

1
2
3
4
5
6
7
8
9
10
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
n = sum(nums)
s = 0
for c, i in enumerate(nums):
n -= i
if s == n:
return c
s += i
return -1

772. Basic Calculator III

日期: 2024/12/18 | 難度: Hard | 分類: Stack、Shunting Yard

題目說明

實作完整計算機,支援 +-*/ 及括號(224 + 227 的合體)。

解題邏輯

Shunting Yard 演算法:中綴轉 RPN 再計算。負號在開頭或括號後補 0-,利用優先級字典 d 控制運算子 pop 時機。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Solution:
def calculate(self, s: str) -> int:
stack = []
tokens = []
d = {'+': 1, '-': 1, '*': 2, '/': 2}
s1 = ''
num = ''
for i in range(len(s)):
if s[i] == ' ':
continue
s1 += s[i]
s = ''
for i in range(len(s1)):
if s1[i] == "-" and (i == 0 or s1[i-1] == "("):
s += "0-"
else:
s += s1[i]
i = 0
while i < len(s):
if s[i].isdigit():
while i < len(s) and s[i].isdigit():
num += s[i]
i += 1
tokens.append(int(num))
i -= 1
num = ''
elif s[i] == "(":
stack.append(s[i])
elif s[i] == ')':
while stack and stack[-1] != '(':
tokens.append(stack.pop())
stack.pop()
else:
while stack and d.get(stack[-1], 0) >= d.get(s[i]):
tokens.append(stack.pop())
stack.append(s[i])
i += 1
while stack:
tokens.append(stack.pop())
l = []
for i in tokens:
if i in ['+', '-', '*', '/']:
a = l.pop()
b = l.pop()
if i == '+': l.append(b + a)
elif i == '-': l.append(b - a)
elif i == '*': l.append(b * a)
elif i == '/': l.append(int(b / a))
else:
l.append(int(i))
return l[0]

790. Domino and Tromino Tiling

日期: 2025/02/18 | 難度: Medium | 分類: 動態規劃

題目說明

用 2×1 的多米諾骨牌和 L 形的 Tromino 鋪滿 2×n 的格子,有幾種方法?結果對 10⁹+7 取模。

解題邏輯

DP 遞推:f[i] = f[i-1]*2 + f[i-3](預先計算好 1001 個值),利用滾動方式求解。

1
2
3
4
5
6
7
8
9
f = [0] * 1001
f[0] = f[1] = 1
f[2] = 2
for i in range(3, 1001):
f[i] = (f[i - 1] * 2 + f[i - 3])

class Solution:
def numTilings(self, n: int) -> int:
return f[n] % 1000000007

872. Leaf-Similar Trees

日期: 2025/02/24 | 難度: Easy | 分類: 樹、DFS

題目說明

判斷兩棵二元樹的葉節點序列(從左到右)是否相同。

解題邏輯

DFS 收集每棵樹的葉節點序列(先左後右),比較兩個序列是否相等。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def leafSimilar(self, root1, root2):
l1, l2 = [], []
def f(node, l):
if not node:
return
if not node.right and not node.left:
return l.append(node.val)
f(node.left, l)
f(node.right, l)
f(root1, l1)
f(root2, l2)
return l1 == l2

875. Koko Eating Bananas

日期: 2025/01/21 | 難度: Medium | 分類: 二分搜尋

題目說明

Koko 在 h 小時內吃完所有香蕉堆,求每小時吃的最小速度 k。

解題邏輯

二分搜尋答案範圍 [1, max(piles)]:對每個速度 mid,計算需要的小時數,若超過 h 則加速(left 右移),否則嘗試更慢(right 左移)。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def minEatingSpeed(self, piles, h) -> int:
from math import ceil
left = 1
right = max(piles)
while left <= right:
mid = (left + right) // 2
if sum(ceil(p / mid) for p in piles) > h:
left = mid + 1
else:
right = mid - 1
return left

1004. Max Consecutive Ones III

日期: 2025/02/18 | 難度: Medium | 分類: 滑動視窗

題目說明

最多可以翻轉 k 個 0,找最長的全 1 子陣列。

解題邏輯

滑動視窗:c 計算視窗內 0 的個數,超過 k 時從左收縮(若移除的是 0 則 c–),持續更新最大視窗長度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
c = 0
io = 0
m = 0
for i in range(len(nums)):
if nums[i] == 0:
c += 1
while c > k:
if nums[io] == 0:
c -= 1
io += 1
if i - io + 1 > m:
m = i - io + 1
return m

1008. Construct Binary Search Tree from Preorder Traversal

日期: 2025/02/18 | 難度: Medium | 分類: 樹、BST

題目說明

給一個 BST 的前序遍歷陣列,重建該 BST。

解題邏輯

遞迴插入:對每個新值,從根開始比較,大於當前節點往右插,小於往左插。依序從前序陣列取值插入即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def bstFromPreorder(self, preorder: List[int]):
def f(node, v):
if not node:
return TreeNode(v)
if node.val < v:
node.right = f(node.right, v)
else:
node.left = f(node.left, v)
return node
if not preorder:
return TreeNode()
tree = TreeNode(preorder.pop(0))
while preorder:
f(tree, preorder.pop(0))
return tree

1207. Unique Number of Occurrences

日期: 2025/02/19 | 難度: Easy | 分類: 雜湊表

題目說明

判斷陣列中每個值的出現次數是否各不相同。

解題邏輯

Counter 取得各值頻次,比較頻次列表的長度和頻次集合的長度,相等則各不相同。

1
2
3
4
5
class Solution:
def uniqueOccurrences(self, arr: List[int]) -> bool:
d = Counter(arr)
l = list(d.values())
return len(l) == len(set(l))

1295. Find Numbers with Even Number of Digits

日期: 2024/12/20 | 難度: Easy | 分類: 陣列

題目說明

找出陣列中位數為偶數的整數個數。

解題邏輯

轉字串取長度,篩選偶數長度的計數。

1
2
3
class Solution:
def findNumbers(self, nums: List[int]) -> int:
return sum(1 for i in nums if len(str(i)) % 2 == 0)

1365. How Many Numbers Are Smaller Than the Current Number

日期: 2024/12/21 | 難度: Easy | 分類: 排序、計數排序

題目說明

對每個元素計算有多少其他元素比它小。

解題邏輯 — 方法一(計數排序)

長度 101 的計數陣列,前綴和即為比當前值小的元素個數。

解題邏輯 — 方法二(排序 + index)

排序後每個元素第一次出現的索引即為答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 方法一
class Solution:
def smallerNumbersThanCurrent(self, nums):
dic = [0] * 101
for i in nums:
dic[i] += 1
return [sum(dic[0:i]) for i in nums]

# 方法二
class Solution:
def smallerNumbersThanCurrent(self, nums):
tmp = sorted(nums)
return [tmp.index(i) for i in nums]

1372. Longest ZigZag Path in a Binary Tree

日期: 2025/02/24 | 難度: Medium | 分類: 樹、DFS

題目說明

找二元樹中最長的鋸齒路徑(交替向左向右),回傳路徑中的節點數減 1。

解題邏輯

DFS 傳遞 (left_len, right_len):往左走時 right_len = left_len + 1,往右走時 left_len = right_len + 1,持續更新全域最大值。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def longestZigZag(self, root):
self.ans = 0
def dfs(node, left, right):
self.ans = max(self.ans, left, right)
if node.left:
dfs(node.left, 0, left + 1)
if node.right:
dfs(node.right, right + 1, 0)
if root:
dfs(root, 0, 0)
return self.ans

1448. Count Good Nodes in Binary Tree

日期: 2025/02/24 | 難度: Medium | 分類: 樹、DFS

題目說明

「好節點」定義為從根到該節點的路徑上,沒有比它更大的節點。計算樹中好節點的數量。

解題邏輯

DFS 傳遞路徑上的最大值,每個節點若 ≥ 路徑最大值則為好節點,計數加 1。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def goodNodes(self, root):
def dfs(node, max_val):
if not node:
return 0
res = 1 if node.val >= max_val else 0
max_val = max(max_val, node.val)
res += dfs(node.left, max_val)
res += dfs(node.right, max_val)
return res
return dfs(root, float('-inf'))

1456. Maximum Number of Vowels in a Substring of Given Length

日期: 2025/02/18 | 難度: Medium | 分類: 滑動視窗

題目說明

給字串 s 和整數 k,找長度為 k 的子字串中母音字母的最多個數。

解題邏輯

固定大小滑動視窗:先計算前 k 個字元的母音數,再移動視窗加新去舊,更新最大值。

1
2
3
4
5
6
7
8
9
class Solution:
def maxVowels(self, s: str, k: int) -> int:
vowels = set('aeiou')
w = sum(1 for c in s[:k] if c in vowels)
m = w
for i in range(k, len(s)):
w += (s[i] in vowels) - (s[i - k] in vowels)
m = max(m, w)
return m

1657. Determine if Two Strings Are Close

日期: 2025/02/19 | 難度: Medium | 分類: 字串、雜湊表

題目說明

兩個字串「接近」的條件:可以通過交換字元位置或交換兩種字元的所有出現來互相轉換。

解題邏輯

兩個條件:(1) 兩字串包含的字元種類相同;(2) 兩字串的字元頻次多重集合相同(sorted 頻次列表相等)。

1
2
3
4
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
c1, c2 = Counter(word1), Counter(word2)
return set(c1) == set(c2) and sorted(c1.values()) == sorted(c2.values())

1679. Max Number of K-Sum Pairs

日期: 2025/02/05 | 難度: Medium | 分類: 雜湊表、雙指針

題目說明

每次選兩個數使其和為 k 並移除,最多能做幾次?

解題邏輯

Counter 記錄頻次,對每個數 n,看 k-n 是否有剩餘,有則配對(兩者各減 1),累計次數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
d = Counter(nums)
res = 0
for n in list(d.keys()):
complement = k - n
if complement in d:
if n == complement:
res += d[n] // 2
d[n] = 0
else:
pairs = min(d[n], d[complement])
res += pairs
d[n] -= pairs
d[complement] -= pairs
return res

1748. Sum of Unique Elements

日期: 2024/12/20 | 難度: Easy | 分類: 雜湊表

題目說明

回傳陣列中只出現一次的元素的總和。

解題邏輯

Counter 篩選出現次數為 1 的元素加總。

1
2
3
class Solution:
def sumOfUnique(self, nums: List[int]) -> int:
return sum(a for a, b in Counter(nums).items() if b == 1)

1768. Merge Strings Alternately

日期: 2025/02/03 | 難度: Easy | 分類: 字串、雙指針

題目說明

交替合併兩個字串(word1[0], word2[0], word1[1], word2[1]…),若一個較長則將其剩餘部分接在末尾。

解題邏輯

zip 配對取出各自字元交替連接,再接上較長字串的剩餘部分。

1
2
3
4
5
6
7
8
9
10
class Solution:
def mergeAlternately(self, word1: str, word2: str) -> str:
res = ''
for a, b in zip(word1, word2):
res += a + b
if len(word1) > len(word2):
res += word1[len(word2):]
else:
res += word2[len(word1):]
return res

2114. Maximum Number of Words Found in Sentences

日期: 2024/12/20 | 難度: Easy | 分類: 字串

題目說明

找句子陣列中單字數最多的句子,回傳最大單字數。

解題邏輯

對每個句子 split() 後取長度,找最大值。

1
2
3
class Solution:
def mostWordsFound(self, sentences: List[str]) -> int:
return max([len(i.split()) for i in sentences])

2215. Find the Difference of Two Arrays

日期: 2025/02/19 | 難度: Easy | 分類: 雜湊集合

題目說明

給兩個陣列,回傳 [在 nums1 但不在 nums2 的元素, 在 nums2 但不在 nums1 的元素]

解題邏輯

轉成集合後用集合差運算,去重後轉回列表。

1
2
3
4
class Solution:
def findDifference(self, nums1: List[int], nums2: List[int]) -> List[List[int]]:
s1, s2 = set(nums1), set(nums2)
return [list(s1 - s2), list(s2 - s1)]

3886. Button With Longest Time

日期: 2024/12/15 | 難度: Medium | 分類: 模擬

題目說明

給按鈕事件列表(每個事件含按鈕索引和時間),找出按下後持續時間最長的按鈕,相同時取索引最小的。

解題邏輯

維護上一事件時間 io,計算每次時間差,字典記錄每個按鈕的最長時間差,最後找最大值對應的最小索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def buttonWithLongestTime(self, events):
d = {}
io = 0
for a, b in events:
t = b - io
if a in d:
if d[a] < t:
d[a] = t
else:
d[a] = t
io = b
m = max(d.values())
return min([i for i, b in d.items() if b == m])

📚 APCS 歷屆考題

APCS(Advanced Placement Computer Science)台灣程式能力檢定,考題涵蓋觀念題與實作題。
題目來自於ZeroJudge


c462. 交錯字串

日期: 2017/10 | 難度: Medium | 分類: 字串處理

題目說明

給整數 k 與字串 s(只含大小寫英文字母)。找出最長連續子字串,滿足「k-交錯」條件:可分成數段,每段正好 k 個相同大小寫,且相鄰段大小寫不同(輸出長度,無符合則0)。

解題邏輯

先把 s 轉成 +1(大寫)/-1(小寫)陣列,對每個起點 i,用 ix=i+k 往右擴展:用狀態機 j 檢查每段 sum 是否達到 ±k 並切換狀態,更新最大有效長度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
k=int(input())
s=input()
a=[1 if i.isupper() else -1 for i in s]
res=0
for i in range(len(a)):
ix=i+k
j=0 #0>k 1>0
while True:
if j==1:
if sum(a[i:ix])==0:
ix+=k
j=0
else:
if ix-i>res:
res=ix-i-k
break
elif j==0:
if a[i]==1 and sum(a[i:ix])==k:
ix+=k
j=1

elif a[i]==-1 and sum(a[i:ix]) ==-k:
ix+=k
j=1
else:
if ix-i>res:
res=ix-i-k
break
if ix>len(a):
if ix-i>res:
res=ix-i-k
break
print(res)

i400. 字串解碼

日期: 2022/6 | 難度: Medium | 分類: 模擬 / 字串

題目說明

給 m 行長度 n 的 01 字串(加密層)+ 一個長度 n 的加密字串 s。從最後一行開始逆推,每層依「1」的數量奇偶,對 s 做特定重排/旋轉,直到恢復原始字串並輸出。

解題邏輯

從最後一行開始逆向處理:對當前 s 從後往前掃,’1’ 尾取、’0’ 頭取,再依 1 的數量奇偶決定是否中間旋轉,更新 s 並 pop 該層,重複直到所有層處理完。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
m, n = map(int, input().split())

l = [input()for i in range(m)]

s = input()

while l:
c = 0
sl = []

for i in range(len(l[-1]) - 1, -1, -1):
if l[-1][i] == '1':
c += 1
sl.append(s[i])
else:
sl.insert(0, s[i])

ins = ""
if c % 2 == 0:
ins = ''.join(sl)
else:
if len(s) % 2 == 0:
mid = len(s) // 2
ins = ''.join(sl[mid:]) + ''.join(sl[:mid])
else:
mid = len(s) // 2
ins = ''.join(sl[mid + 1:]) + sl[mid] + ''.join(sl[:mid])

s = ins
l.pop()

print(s)

m931. 遊戲選角

日期: 2024/1 | 難度: Easy | 分類: 排序 / 模擬

題目說明

輸入 n 個角色(每個有攻擊力 x、防禦力 y),能力值 = x² + y²。輸出能力值第二大的角色的 x y(保證所有能力值不同)。

解題邏輯

把每個點存成 list,計算 dist² 放 dict(key=索引),用 sorted(key=d.get, reverse=True) 取出第二大索引,直接印出對應的 x y。

1
2
3
4
5
6
7
8
n=int(input())
l=[list(map(int,input().split()))for i in range(n)]
d={}
for i in range(n):
ans=l[i][0]**2+l[i][1]**2
d[i]=ans
k=sorted(d,key=d.get,reverse=True)
print(*l[k[1]])

m932. 蜜蜂觀察

日期: 2024/1 | 難度: Easy | 分類: 模擬

題目說明

m×n 字母蜂巢(大寫/小寫視為不同),蜜蜂從左下角開始,給一系列移動指令(0~5 六種方向)。撞牆壁/邊界不動。收集走過的所有格字母成字串,最後輸出字串 + 不同字母種類數。

解題邏輯

grid 讀成 list,起點 y=a-1、x=0,用 if 判斷每個指令的邊界條件移動後 s += 當前格字母,最後 print(s) 與 len(set(s))。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
a,b,c=map(int,input().split())
l=[[i for i in input()]for i in range(a)]
nums=list(map(int,input().split()))
s=''
y=a-1
x=0
for i in nums:
if i==0:
if y!=0:
y-=1
if i==1:
if x!=(b-1):
x+=1
if i==2:
if x!=(b-1) and y!=(a-1):
y+=1
x+=1
if i==3:
if y!=(a-1):
y+=1
if i==4:
if x!=0:
x-=1
if i==5:
if y!=0 and x!=0:
x-=1
y-=1
s+=l[y][x]
print(s)

print(len(set([i for i in s])))

o712. 蒐集寶石

日期: 2024/10 | 難度: Medium | 分類: 模擬

題目說明

M×N 地圖(數字=寶石數,-1=牆),機器人從 (r,c) 開始朝右。當前格 >0 就撿1顆(格-1、score+1),score 是 k 的倍數就右轉90°。若前方是牆/出界就繼續右轉,直到能走。當前格變0就停止,輸出總撿寶石數。

解題邏輯

外 while(當前格 !=0):撿寶石、計數+1、若 s%k==0 就 f=(f+1)%4。內 while 用四個方向 if 檢查下一格是否可走,不能走就繼續轉向,直到移動成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
M, N, k, r, c = map(int, input().split())
l = [list(map(int, input().split())) for i in range(M)]
s = 0
f = 0
b = 0

while l[r][c] != 0:
t = 1
s += l[r][c]
b += 1
l[r][c] -= 1
if s % k == 0:
f += 1
f %= 4

while t == 1:

if f == 0 and c + 1 < N:
if l[r][c + 1] != -1:
c += 1
t = 0
else:
f += 1
f %= 4
elif f == 1 and r + 1 < M:
if l[r + 1][c] != -1:
r += 1
t = 0
else:
f += 1
f %= 4
elif f == 2 and c - 1 >= 0:
if l[r][c - 1] != -1:
c -= 1
t = 0
else:
f += 1
f %= 4
elif f == 3 and r - 1 >= 0:
if l[r - 1][c] != -1:
r -= 1
t = 0
else:
f += 1
f %= 4
else:
f+=1
f %= 4

print(b)

q836. 小心陷阱

日期: 2025/6 | 難度: Easy | 分類: 模擬

題目說明

數線位置從0開始,初始生命 k。每次以當前生命 v 往右跳 v 格(p += v),落地後若 p 是 x1 倍數扣 y1、是 x2 倍數扣 y2。生命 ≤0 停止,輸出最終位置 p。

解題邏輯

while k>0:p += k(當前生命跳),然後檢查 p%x1==0 或 %x2==0 就從 k 扣對應 y,直到 k≤0 輸出 p。

1
2
3
4
5
6
7
8
9
10
11
k=int(input())
x1,y1=map(int,input().split())
x2,y2=map(int,input().split())
p=0
while k>0:
p+=k
if p%x1==0:
k-=y1
if p%x2==0:
k-=y2
print(p)

q837. 轉盤得分

日期: 2025/6 | 難度: Medium | 分類: 模擬 / 陣列

題目說明

m 個長度 n 的字母轉盤,進行 k 輪操作。每輪給 m 個旋轉值,對每個轉盤旋轉後,每一直行取該行最多相同字母的出現次數,加總所有直行的 max 值得到該輪得分,最後輸出 k 輪總分。

解題邏輯

對 k 組 values,每組先對每行做 s = s[-p:] + s[:-p] 旋轉,再 zip(*l) 看每直行,用 max(i.count(j) for j in i) 累加到 ans。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
m,n,k=map(int,input().split())
l=[input()for i in range(m)]
t=[]

ans=0
for values in [list(map(int, input().split()))for _ in range(k)]:

for i in range(m):
s = l[i]
p = values[i] % n
s = s[-p:] + s[:-p]
l[i] = s

for i in zip(*l):
ans+=max(i.count(j)for j in i)
print(ans)

q838. 貪心闖關

日期: 2025/6 | 難度: Medium | 分類: 貪心 / 堆疊

題目說明

n 關卡各有沙包數 l[i]。重複操作:選當前最少沙包的關卡,把它的沙包全部搬到下一個非空關卡,每搬1沙包得1分。算總得分。

解題邏輯

用 stack 模擬:遇到 x 時 while st and st[-1] <= x 就合併(ans += st[-1]、x += st[-1]、pop),若 x <= t 才 push。最後把剩餘 stack 全部加到 ans。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
n, t = map(int, input().split())
st = []
ans = 0
l = list(map(int, input().split()))
for i in range(n):
x = l[i]
while st and st[-1] <= x:
ans += st[-1]
x += st[-1]
st.pop()
if x <= t:
st.append(x)
for x in st:
ans += x
print(ans)

📊 leetcode題目總覽

題號 題目名稱 難度 日期 核心技巧
1 Two Sum Easy 2025/02/05 雜湊表
3 Longest Substring Without Repeating Characters Medium 2025/01/15 滑動視窗
9 Palindrome Number Easy 2024/12/20 字串反轉
11 Container With Most Water Medium 2025/02/05 雙指針
13 Roman to Integer Easy 2024/12/21 字串映射
14 Longest Common Prefix Easy 2024/12/21 字串
22 Generate Parentheses Medium 2025/01/24 回溯
26 Remove Duplicates from Sorted Array Easy 2024/12/15 Set
27 Remove Element Easy 2024/12/22 雙指針
28 Find the Index of First Occurrence Easy 2024/12/23 字串
36 Valid Sudoku Medium 2025/01/16 雜湊集合
39 Combination Sum Medium 2024/12/31 回溯
40 Combination Sum II Medium 2024/12/31 回溯
43 Multiply Strings Medium 2025/01/24 模擬乘法
46 Permutations Medium 2025/01/03 回溯
47 Permutations II Medium 2025/01/04 回溯
53 Maximum Subarray Medium 2024/12/16 Kadane’s
54 Spiral Matrix Medium 2024/12/29 邊界模擬
55 Jump Game Medium 2024/12/25 貪心
59 Spiral Matrix II Medium 2025/01/21 邊界模擬
62 Unique Paths Medium 2025/01/05 DP
63 Unique Paths II Medium 2025/01/15 DP
67 Add Binary Easy 2024/12/22 進位制轉換
70 Climbing Stairs Easy 2024/12/17 DP、費波那契
73 Set Matrix Zeroes Medium 2024/12/29 矩陣模擬
75 Sort Colors Medium 2025/01/21 三指針
77 Combinations Medium 2024/12/30 回溯
78 Subsets Medium 2024/12/30 回溯
88 Merge Sorted Array Easy 2024/12/20 雙指針
90 Subsets II Medium 2025/01/15 回溯
91 Decode Ways Medium 2025/01/04 DP
100 Same Tree Easy 2025/01/07 遞迴
101 Symmetric Tree Easy 2025/01/07 BFS
102 Binary Tree Level Order Traversal Medium 2025/01/14 BFS
104 Maximum Depth of Binary Tree Easy 2025/01/07 遞迴
107 Binary Tree Level Order Traversal II Medium 2025/01/14 BFS
111 Minimum Depth of Binary Tree Easy 2025/01/07 遞迴
112 Path Sum Easy 2025/01/08 遞迴
118 Pascal’s Triangle Easy 2024/12/22 DP
119 Pascal’s Triangle II Easy DP
121 Best Time to Buy and Sell Stock Easy 2024/12/16 貪心
122 Best Time to Buy and Sell Stock II Medium 2025/01/15 貪心
136 Single Number Easy 2024/12/17 XOR
137 Single Number II Medium 2024/12/17 位元遮罩
150 Evaluate Reverse Polish Notation Medium 2024/12/18 Stack
151 Reverse Words in a String Medium 2025/01/24 字串
168 Excel Sheet Column Title Easy 2025/01/02 進位制
189 Rotate Array Medium 2024/12/15 切片
198 House Robber Medium 2024/12/24 DP
202 Happy Number Easy 2024/12/23 集合
205 Isomorphic Strings Easy 2024/12/24 雜湊表
209 Minimum Size Subarray Sum Medium 2025/01/21 滑動視窗
213 House Robber II Medium 2024/12/25 DP
216 Combination Sum III Medium 2025/01/04 回溯
219 Contains Duplicate II Easy 2024/12/27 雜湊表
224 Basic Calculator Hard 2024/12/18 Stack
226 Invert Binary Tree Easy 2025/01/13 遞迴
227 Basic Calculator II Medium 2024/12/18 Stack
240 Search a 2D Matrix II Medium 2025/01/24 雙指針
242 Valid Anagram Easy 2024/12/17 Counter
257 Binary Tree Paths Easy 2025/01/09 DFS
263 Ugly Number Easy 2025/01/03 數學
283 Move Zeroes Easy 2024/12/16 陣列
290 Word Pattern Easy 2024/12/28 雜湊表
300 Longest Increasing Subsequence Medium 2025/01/05 DP
322 Coin Change Medium 2025/01/24 DP
334 Increasing Triplet Subsequence Medium 2025/02/03 貪心
338 Counting Bits Easy 2025/01/02 DP + 位元
342 Power of Four Easy 2025/01/02 位元運算
344 Reverse String Easy 2024/12/23 雙指針
345 Reverse Vowels of a String Easy 2025/02/03 雙指針
350 Intersection of Two Arrays II Easy 2024/12/15 雜湊表
371 Sum of Two Integers Medium 2024/12/28 位元運算
383 Ransom Note Easy 2025/01/03 Counter
387 First Unique Character in a String Easy 2024/12/23 Counter
389 Find the Difference Easy 2024/12/17 ASCII
392 Is Subsequence Easy 2025/02/05 雙指針
404 Sum of Left Leaves Easy 2025/01/09 遞迴
405 Convert a Number to Hexadecimal Easy 2025/01/02 位元運算
409 Longest Palindrome Easy 2024/12/27 計數
435 Non-overlapping Intervals Medium 2025/01/05 貪心
437 Path Sum III Medium 2025/02/24 前綴和
443 String Compression Medium 2025/02/03 雙指針
448 Find All Numbers Disappeared in an Array Easy 2024/12/27 標記法
463 Island Perimeter Easy 2024/12/28 矩陣
476 Number Complement Easy 2025/01/02 位元運算
494 Target Sum Medium 2025/01/24 DP
496 Next Greater Element I Easy 2024/12/28 單調堆疊
500 Keyboard Row Easy 2024/12/27 集合
543 Diameter of Binary Tree Easy 2025/01/13 DFS
556 Next Greater Element III Medium 2024/12/28 Next Permutation
561 Array Partition Easy 2024/12/24 排序
572 Subtree of Another Tree Easy 2025/01/13 遞迴
575 Distribute Candies Easy 2024/12/26 集合
581 Shortest Unsorted Continuous Subarray Medium 2025/01/05 排序比較
637 Average of Levels in Binary Tree Easy 2025/01/13 BFS
643 Maximum Average Subarray I Easy 2025/02/05 滑動視窗
704 Binary Search Easy 2024/12/20 二分搜尋
724 Find Pivot Index Easy 2024/12/20 前綴和
772 Basic Calculator III Hard 2024/12/18 Shunting Yard
790 Domino and Tromino Tiling Medium 2025/02/18 DP
872 Leaf-Similar Trees Easy 2025/02/24 DFS
875 Koko Eating Bananas Medium 2025/01/21 二分搜尋
1004 Max Consecutive Ones III Medium 2025/02/18 滑動視窗
1008 Construct BST from Preorder Traversal Medium 2025/02/18 BST
1207 Unique Number of Occurrences Easy 2025/02/19 Counter
1295 Find Numbers with Even Number of Digits Easy 2024/12/20 字串轉換
1365 How Many Numbers Are Smaller Than Current Easy 2024/12/21 計數排序
1372 Longest ZigZag Path in a Binary Tree Medium 2025/02/24 DFS
1448 Count Good Nodes in Binary Tree Medium 2025/02/24 DFS
1456 Maximum Number of Vowels in a Substring Medium 2025/02/18 滑動視窗
1657 Determine if Two Strings Are Close Medium 2025/02/19 Counter
1679 Max Number of K-Sum Pairs Medium 2025/02/05 Counter
1748 Sum of Unique Elements Easy 2024/12/20 Counter
1768 Merge Strings Alternately Easy 2025/02/03 字串
2114 Maximum Number of Words Found in Sentences Easy 2024/12/20 split()
2215 Find the Difference of Two Arrays Easy 2025/02/19 集合
3886 Button With Longest Time Medium 2024/12/15 模擬
Comments