Python2026

来自linuxsa wiki
跳转到导航 跳转到搜索

part 1

每天都做成详细的 step-by-step 计划。

---

## Day 1 — 字符串操作(60-90分钟) Done March 03

### 第一步:看这些操作,每个自己手打一遍(20分钟)
```python
s = "Hello World"

# 基础操作
print(s[::-1])           # 反转 → "dlroW olleH"
print(s.upper())         # 全大写
print(s.lower())         # 全小写
print(s.strip())         # 去首尾空格
print(s.split(" "))      # 分割 → ["Hello", "World"]
print("-".join(["a","b","c"]))  # 合并 → "a-b-c"
print(s.replace("l","x"))       # 替换
print(s.count("l"))      # 统计出现次数 → 3
print(s.find("World"))   # 找位置 → 6
print(s.startswith("He")) # True
print(s.isdigit())       # 是否全是数字
print(s.isalpha())       # 是否全是字母
```

### 第二步:把这 3 个模板理解并默写(15分钟)
```python
# 模板1:判断回文
def is_palindrome(s):
    s = s.lower().replace(" ", "")  # 忽略大小写和空格
    return s == s[::-1]

# 模板2:统计每个字符频率
from collections import Counter
def char_frequency(s):
    return Counter(s)

# 模板3:反转句子里的单词顺序
def reverse_words(s):
    return " ".join(s.split()[::-1])

# 测试
print(is_palindrome("A man a plan a canal Panama"))  # True
print(char_frequency("hello"))  # Counter({'l':2,'h':1,'e':1,'o':1})
print(reverse_words("hello world foo"))  # "foo world hello"
```

### 第三步:去 HackerRack 做这 3 道题(30-45分钟)
1. **Reverse a String** — 搜索直接做
2. **String Validators** — 考 isdigit/isalpha/isupper
3. **Capitalize** — 考 split + join + capitalize()

> HackerRank 注册后 → 选 Python → Practice → Strings

### 今天结束前问自己:
- [ ] `s[::-1]` 和 `s.split()` 不看笔记能写出来吗?
- [ ] 3 道题都通过了吗?
- [ ] 有没有遇到边界条件出错(空字符串)?

---

## Day 2 — 列表 & 推导式(60-90分钟)

### 第一步:手打这些操作(20分钟)
```python
lst = [3, 1, 4, 1, 5, 9, 2, 6, 5]

print(sorted(lst))               # 升序(不改原列表)
print(sorted(lst, reverse=True)) # 降序
print(max(lst), min(lst))        # 最大最小
print(sum(lst))                  # 求和
print(lst.count(5))              # 5 出现几次 → 2
print(list(set(lst)))            # 去重(顺序不保证)

# enumerate 和 zip(很常用)
for i, val in enumerate(lst):
    print(f"index {i}: {val}")

for a, b in zip([1,2,3], ["x","y","z"]):
    print(a, b)
```

### 第二步:列表推导式重点练(15分钟)
```python
# 基础
squares = [x**2 for x in range(10)]

# 带条件过滤
evens = [x for x in range(20) if x % 2 == 0]

# 嵌套(二维矩阵)
matrix = [[i*j for j in range(1,4)] for i in range(1,4)]

# 字符串 + 列表组合
words = ["hello", "world", "python"]
upper_words = [w.upper() for w in words if len(w) > 4]

print(squares)
print(evens)
print(matrix)
print(upper_words)
```

### 第三步:把这个模板理解并默写(15分钟)
```python
# 两数之和(最经典的 Easy 题)
def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        complement = target - n
        if complement in seen:
            return [seen[complement], i]
        seen[n] = i
    return []

print(two_sum([2,7,11,15], 9))   # [0, 1]
print(two_sum([3,2,4], 6))       # [1, 2]
print(two_sum([], 5))            # [] ← 边界条件
```

### 第三步:HackerRank 做这 3 道题
1. **List Comprehensions**
2. **Find the Runner-Up Score**
3. **Nested Lists**

---

## Day 3 — 字典 & 集合(60-90分钟)

### 第一步:手打操作(15分钟)
```python
d = {"name": "Alice", "age": 25}

# 安全取值(不会 KeyError)
print(d.get("name"))          # Alice
print(d.get("salary", 0))     # 0(默认值)

# 遍历
for k, v in d.items():
    print(k, v)

# 集合运算
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a & b)   # 交集 {3, 4}
print(a | b)   # 并集 {1,2,3,4,5,6}
print(a - b)   # 差集 {1, 2}
```

### 第二步:defaultdict 专项练习(15分钟)
```python
from collections import defaultdict

# 场景1:统计词频(比普通 dict 方便很多)
def word_count(sentence):
    freq = defaultdict(int)
    for word in sentence.split():
        freq[word] += 1
    return dict(freq)

# 场景2:按某个属性分组
def group_by_length(words):
    groups = defaultdict(list)
    for w in words:
        groups[len(w)].append(w)
    return dict(groups)

print(word_count("the cat sat on the mat the cat"))
# {'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1}

print(group_by_length(["hi","hello","hey","world","ok"]))
# {2: ['hi', 'ok'], 5: ['hello', 'world'], 3: ['hey']}
```

### 第三步:Counter 专项(10分钟)
```python
from collections import Counter

# 最常用的操作
c = Counter("abracadabra")
print(c)                    # 每个字符的频率
print(c.most_common(3))     # 前3个最常见的
print(c["a"])               # a 出现几次
print(list(c.keys()))       # 所有出现的字符

# 找出现次数最多的字符,并列时取字母最小的
def most_frequent_char(s):
    c = Counter(s)
    max_count = max(c.values())
    candidates = [ch for ch, cnt in c.items() if cnt == max_count]
    return min(candidates)  # 字母最小的

print(most_frequent_char("aabbcc"))  # a
```

### 第四步:HackerRank 做这 3 道
1. **Collections.Counter()**
2. **DefaultDict Tutorial**
3. **Word Order**

---

## Day 4 — 数学逻辑(60分钟)

### 第一步:把这 5 个模板全部默写出来(30分钟)

不要看笔记,直接默写,写不出来再看:

```python
import math

# 1. FizzBuzz
def fizzbuzz(n):
    for i in range(1, n+1):
        if i % 15 == 0: print("FizzBuzz")
        elif i % 3 == 0: print("Fizz")
        elif i % 5 == 0: print("Buzz")
        else: print(i)

# 2. 判断质数
def is_prime(n):
    if n < 2: return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0: return False
    return True

# 3. 斐波那契(返回第 n 个)
def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

# 4. 最大公约数 & 最小公倍数
def gcd(a, b): return math.gcd(a, b)
def lcm(a, b): return a * b // math.gcd(a, b)

# 5. 数字各位求和
def digit_sum(n):
    return sum(int(d) for d in str(abs(n)))

# 测试
fizzbuzz(15)
print([n for n in range(20) if is_prime(n)])
print([fibonacci(i) for i in range(10)])
print(gcd(48, 18), lcm(4, 6))
print(digit_sum(12345))
```

### 第二步:HackerRank 做
1. **Integers Come In All Sizes**
2. **Triangle Quest**
3. 任意一道 Math Easy 题

---

## Day 5 — 排序进阶(60分钟)

### 第一步:lambda 排序练习(20分钟)
```python
# 场景1:按元组第二个元素排序
students = [("Alice",85), ("Bob",92), ("Charlie",78), ("Dave",85)]
print(sorted(students, key=lambda x: x[1]))           # 按分数升序
print(sorted(students, key=lambda x: x[1], reverse=True))  # 降序

# 场景2:按多个条件排序(先按分数降序,分数相同按名字升序)
print(sorted(students, key=lambda x: (-x[1], x[0])))

# 场景3:按字符串长度排序,长度相同按字母顺序
words = ["banana","apple","kiwi","fig","cherry"]
print(sorted(words, key=lambda x: (len(x), x)))

# 场景4:对字典列表排序
people = [{"name":"Alice","age":30}, {"name":"Bob","age":25}]
print(sorted(people, key=lambda x: x["age"]))
```

### 第二步:双指针模板(20分钟)
```python
# 模板1:判断回文
def is_palindrome(lst):
    left, right = 0, len(lst) - 1
    while left < right:
        if lst[left] != lst[right]: return False
        left += 1
        right -= 1
    return True

# 模板2:找数组中两个数之和等于 target(数组已排序)
def two_sum_sorted(nums, target):
    left, right = 0, len(nums) - 1
    while left < right:
        s = nums[left] + nums[right]
        if s == target: return [left, right]
        elif s < target: left += 1
        else: right -= 1
    return []

print(is_palindrome([1,2,3,2,1]))   # True
print(two_sum_sorted([1,3,5,7,9], 8))  # [0, 3]
```

### 第三步:自己写一道题
> 给一个字符串列表,先按字符串长度排序,长度相同的按字母倒序排。写完测试边界:空列表、只有一个元素。

---

## Day 6 — 栈 & 队列(60分钟)

### 第一步:基础操作(10分钟)
```python
from collections import deque

# 栈(LIFO)
stack = []
stack.append("a")
stack.append("b")
print(stack.pop())   # b
print(stack[-1])     # 查看栈顶不弹出

# 队列(FIFO)
queue = deque()
queue.append(1)
queue.append(2)
print(queue.popleft())  # 1(从左边出)
```

### 第二步:括号匹配(最经典栈题,必须会)(20分钟)
```python
def is_valid(s):
    stack = []
    mapping = {")": "(", "}": "{", "]": "["}
    for char in s:
        if char in mapping:
            top = stack.pop() if stack else "#"
            if mapping[char] != top:
                return False
        else:
            stack.append(char)
    return not stack

# 测试(包括边界条件)
print(is_valid("()[]{}"))   # True
print(is_valid("([)]"))     # False
print(is_valid("{[]}"))     # True
print(is_valid(""))         # True(空字符串)
print(is_valid("]"))        # False(只有右括号)
```

### 第三步:用栈解一道实际题(20分钟)
```python
# 题目:给一个整数数组,用栈找出每个元素右边第一个比它大的数
# 输入: [2, 1, 2, 4, 3]
# 输出: [4, 2, 4, -1, -1](没有则返回 -1)

def next_greater(nums):
    result = [-1] * len(nums)
    stack = []  # 存 index
    for i, n in enumerate(nums):
        while stack and nums[stack[-1]] < n:
            idx = stack.pop()
            result[idx] = n
        stack.append(i)
    return result

print(next_greater([2, 1, 2, 4, 3]))  # [4, 2, 4, -1, -1]
```

---

## Day 7 — 复盘日(45分钟)

### Step 1:做一张自己的错题表(15分钟)

回顾这一周,记录:
- 哪类题最容易出错?
- 哪个语法经常忘?
- 边界条件有没有经常漏掉?

### Step 2:不看笔记,默写这些模板(20分钟)
```
1. 判断回文
2. 统计字符频率(Counter)
3. 两数之和(用 dict)
4. 判断质数
5. 括号匹配(用栈)
```

### Step 3:限时做 2 道综合题(30分钟,每题15分钟)

题目1:
> 给一个字符串,找出第一个不重复的字符,返回它的 index。如果不存在返回 -1。
> 例:"leetcode" → 0,"aabb" → -1

题目2:
> 给一个整数数组,返回乘积最大的三个数之积。
> 例:[1,2,3,4] → 24,[-10,-10,1,3,2] → 300

---

## Day 8 — 二维数组(60分钟)

### 第一步:基础操作(15分钟)
```python
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

rows = len(matrix)
cols = len(matrix[0])

# 遍历
for i in range(rows):
    for j in range(cols):
        print(matrix[i][j], end=" ")
    print()

# 转置
transposed = list(map(list, zip(*matrix)))
# [[1,4,7],[2,5,8],[3,6,9]]

# 对角线元素
main_diag = [matrix[i][i] for i in range(rows)]          # [1,5,9]
anti_diag = [matrix[i][rows-1-i] for i in range(rows)]   # [3,5,7]
```

### 第二步:常见考题(30分钟)
```python
# 1. 顺时针旋转 90 度
def rotate_90(matrix):
    return [list(row) for row in zip(*matrix[::-1])]

# 2. 螺旋遍历(偶尔出)
def spiral_order(matrix):
    result = []
    while matrix:
        result += matrix.pop(0)
        matrix = list(zip(*matrix))[::-1]
    return result

print(rotate_90([[1,2,3],[4,5,6],[7,8,9]]))
print(spiral_order([[1,2,3],[4,5,6],[7,8,9]]))
```

---

## Day 9 — 递归(60分钟)

### 第一步:理解递归三要素(10分钟)
```
1. 终止条件(base case)
2. 递归调用(缩小问题规模)
3. 返回值
```

### 第二步:练习这 3 个(30分钟)
```python
# 1. 二分搜索
def binary_search(arr, target, left=0, right=None):
    if right is None: right = len(arr) - 1
    if left > right: return -1
    mid = (left + right) // 2
    if arr[mid] == target: return mid
    elif arr[mid] < target: return binary_search(arr, target, mid+1, right)
    else: return binary_search(arr, target, left, mid-1)

# 2. 幂运算
def power(base, exp):
    if exp == 0: return 1
    if exp % 2 == 0:
        half = power(base, exp // 2)
        return half * half
    return base * power(base, exp - 1)

# 3. 展平嵌套列表
def flatten(lst):
    result = []
    for item in lst:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result

print(binary_search([1,3,5,7,9,11], 7))  # 3
print(power(2, 10))                       # 1024
print(flatten([1,[2,[3,4]],5]))           # [1,2,3,4,5]
```

---

## Day 10 — 补弱点日

### 根据你第 7 天的错题表,选对应的练习:

**如果字符串是弱点:**
- 做 HackerRank → Strings 里 5 道你没做过的题

**如果排序/lambda 是弱点:**
```python
# 专练这类题
data = [("Alice",85,"F"), ("Bob",92,"M"), ("Charlie",85,"M")]
# 按分数降序,分数相同按名字升序排
sorted(data, key=lambda x: (-x[1], x[0]))
```

**如果边界条件是弱点:**
- 把 Day 1-6 所有模板加上这些测试用例重跑一遍:
```python
# 空输入
func([])
func("")
# 单个元素
func([1])
func("a")
# 负数
func([-1, -2, -3])
# 全相同
func([5,5,5,5])
```

---

## Day 11 — 限时模拟①(60分钟)

### 规则
- 3 道题,每题严格 **15 分钟**,计时器一定要开
- 时间到了立刻停,不管写没写完
- 剩余 15 分钟复盘

### 今日题目(自己去 HackerRank 找同类型):

**题1(字符串):** 给一个字符串,判断它是否是另一个字符串的字母异位词(anagram)
```
"listen" 和 "silent" → True
"hello" 和 "world" → False
```

**题2(数组):** 给一个数组,找出所有出现次数超过 n//2 的元素
```
[3,2,3] → [3]
[1,1,1,2,2,3] → [1]
```

**题3(数学):** 给一个数,判断它是不是完全平方数,不能用 sqrt
```
16 → True
14 → False
```

### 15分钟复盘:
- 哪道题超时了?为什么?
- 有没有边界条件没考虑到?

---

## Day 12 — 限时模拟②(60分钟)

### 完全模拟 SHL 节奏:2 道题,45 分钟

**题1:**
> 给一个字符串,找出出现次数最多的字符。如果有多个字符次数相同,返回字母表中最小的那个。空字符串返回空字符串。

```python
# 期望输出
most_frequent("aabbbcc") → "b"
most_frequent("aabb")    → "a"
most_frequent("")         → ""
```

**题2:**
> 给一个整数数组和目标值 target,找出数组中所有和等于 target 的不重复二元组,返回列表。

```python
# 期望输出
find_pairs([1,2,3,4,5,6], 7) → [(1,6),(2,5),(3,4)]
find_pairs([1,1,2,3], 4)     → [(1,3)]  # 不重复
find_pairs([], 5)             → []
```

**做完之后对答案:** 所有测试用例过了吗?

---

## Day 13 — 边界条件专项(45分钟)

### 把这 6 类边界条件变成习惯

每道题写完之前都问自己这 6 个问题:

```python
"""
1. 输入为空?         → [] 或 "" 或 None
2. 只有一个元素?     → 不要假设 len >= 2
3. 有负数?           → 数学逻辑还成立吗
4. 有重复元素?       → 去重逻辑对吗
5. 返回类型对吗?     → 要 list 别返回 tuple,要 int 别返回 float
6. 数字超大?         → Python 不会溢出,但逻辑还对吗
"""

# 练习:给下面这个函数加边界条件处理
def find_max_pair_sum(nums):
    # 找两个数之和的最大值
    nums.sort()
    return nums[-1] + nums[-2]

# 问题:如果 nums 是空列表?如果只有一个元素?
# 修复版:
def find_max_pair_sum_safe(nums):
    if len(nums) < 2: return None  # 或者 raise ValueError
    nums.sort()
    return nums[-1] + nums[-2]
```

### 专项练习:把 Day 11-12 的题全部加上边界测试重跑一遍

---

## Day 14 — 考前最终模拟(75分钟)

### 模拟考试(60分钟)

找安静的地方,手机放一边,**不查任何资料**:

**题1:** 给一个句子,返回其中最长的单词。如果有多个同样长的,返回第一个出现的。

**题2:** 给一个正整数,判断它是否是回文数(不转成字符串来做)。

**题3:** 给两个列表 A 和 B,找出所有在 A 中出现但不在 B 中的元素,以及在 B 中出现但不在 A 中的元素,合并返回(去重,升序)。

### 最后15分钟:检查清单

```
✅ 每道题的边界条件都处理了吗?
✅ 函数有 return 吗(别忘了返回值)?
✅ 测试用例都跑过了吗?
✅ 变量名是否清晰(别用 a/b/x 这种)?
```

### 考试当天记住

- 先**读完所有题目**,从最有把握的开始
- 能通过部分测试用例也比完全不提交好
- 代码**能跑通**比最优解更重要
- 时间不够时,优先保证已写部分是对的

---



想要我帮你出每天的参考答案,或者模拟出题吗?

part 2

好的!给你每天的题目 + 参考答案,全部整理成一个完整的文档。好的,现在我来创建一个完整的 Word 文档,包含每天的题目和参考答案。Bash 在这个会话里被限制了,我直接给你完整的每天题目和答案,内容非常详细。

---

# 两周每日题目 + 参考答案

---

## Day 1 — 字符串

### 题目1:判断回文
> 给一个字符串,忽略大小写和空格,判断是否是回文。

```python
# 你的答案写这里
def is_palindrome(s):
    pass

# 测试用例
print(is_palindrome("racecar"))        # True
print(is_palindrome("Hello"))          # False
print(is_palindrome("A man a plan a canal Panama"))  # True
print(is_palindrome(""))               # True
print(is_palindrome("a"))             # True
```

**参考答案:**
```python
def is_palindrome(s):
    s = s.lower().replace(" ", "")
    return s == s[::-1]
```

---

### 题目2:找出现次数最多的字符
> 给一个字符串,找出现次数最多的字符。并列时返回字母表最小的。空字符串返回空字符串。

```python
def most_frequent_char(s):
    pass

print(most_frequent_char("aabbbcc"))   # "b"
print(most_frequent_char("aabb"))      # "a"
print(most_frequent_char(""))          # ""
print(most_frequent_char("z"))         # "z"
```

**参考答案:**
```python
from collections import Counter

def most_frequent_char(s):
    if not s:
        return ""
    c = Counter(s)
    max_count = max(c.values())
    candidates = [ch for ch, cnt in c.items() if cnt == max_count]
    return min(candidates)
```

---

### 题目3:反转句子中的单词
> 给一个句子,把每个单词的顺序反转,但每个单词内部字母顺序不变。

```python
def reverse_words(s):
    pass

print(reverse_words("hello world"))        # "world hello"
print(reverse_words("I love Python"))      # "Python love I"
print(reverse_words("  spaces   here  ")) # "here spaces"
print(reverse_words(""))                   # ""
```

**参考答案:**
```python
def reverse_words(s):
    return " ".join(s.split()[::-1])
```

---

## Day 2 — 列表

### 题目1:两数之和
> 给一个整数数组和目标值,返回加起来等于目标值的两个元素的下标。

```python
def two_sum(nums, target):
    pass

print(two_sum([2, 7, 11, 15], 9))    # [0, 1]
print(two_sum([3, 2, 4], 6))         # [1, 2]
print(two_sum([3, 3], 6))            # [0, 1]
print(two_sum([], 5))                # []
```

**参考答案:**
```python
def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        complement = target - n
        if complement in seen:
            return [seen[complement], i]
        seen[n] = i
    return []
```

---

### 题目2:找第二大的数
> 给一个整数数组,找出第二大的数。如果不存在返回 None。

```python
def second_largest(nums):
    pass

print(second_largest([3, 1, 4, 1, 5, 9]))  # 5
print(second_largest([1, 1, 1]))            # None
print(second_largest([5]))                  # None
print(second_largest([]))                   # None
print(second_largest([-1, -2, -3]))        # -2
```

**参考答案:**
```python
def second_largest(nums):
    unique = list(set(nums))
    if len(unique) < 2:
        return None
    unique.sort()
    return unique[-2]
```

---

### 题目3:移动零到末尾
> 给一个整数数组,把所有 0 移动到末尾,其他元素保持相对顺序。

```python
def move_zeros(nums):
    pass

print(move_zeros([0, 1, 0, 3, 12]))   # [1, 3, 12, 0, 0]
print(move_zeros([0, 0, 0]))           # [0, 0, 0]
print(move_zeros([1, 2, 3]))           # [1, 2, 3]
print(move_zeros([]))                  # []
```

**参考答案:**
```python
def move_zeros(nums):
    non_zero = [x for x in nums if x != 0]
    zeros = [0] * nums.count(0)
    return non_zero + zeros
```

---

## Day 3 — 字典 & 集合

### 题目1:统计词频
> 给一个句子,返回每个单词出现的次数(字典),忽略大小写。

```python
def word_frequency(sentence):
    pass

print(word_frequency("the cat sat on the mat the cat"))
# {'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1}
print(word_frequency("Hello hello HELLO"))
# {'hello': 3}
print(word_frequency(""))
# {}
```

**参考答案:**
```python
from collections import defaultdict

def word_frequency(sentence):
    if not sentence.strip():
        return {}
    freq = defaultdict(int)
    for word in sentence.lower().split():
        freq[word] += 1
    return dict(freq)
```

---

### 题目2:两个列表的差集
> 给两个列表 A 和 B,找出只在 A 中出现、不在 B 中的元素,以及只在 B 中出现、不在 A 中的元素,合并去重后升序返回。

```python
def symmetric_difference(a, b):
    pass

print(symmetric_difference([1,2,3,4], [3,4,5,6]))  # [1, 2, 5, 6]
print(symmetric_difference([1,2], [1,2]))           # []
print(symmetric_difference([], [1,2,3]))            # [1, 2, 3]
print(symmetric_difference([1,1,2], [2,3,3]))       # [1, 3]
```

**参考答案:**
```python
def symmetric_difference(a, b):
    set_a, set_b = set(a), set(b)
    result = (set_a - set_b) | (set_b - set_a)
    return sorted(result)
```

---

### 题目3:按字母分组
> 给一个单词列表,按首字母分组,返回字典。

```python
def group_by_first_letter(words):
    pass

print(group_by_first_letter(["apple","banana","avocado","blueberry","cherry"]))
# {'a': ['apple', 'avocado'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}
print(group_by_first_letter([]))
# {}
```

**参考答案:**
```python
from collections import defaultdict

def group_by_first_letter(words):
    groups = defaultdict(list)
    for word in words:
        groups[word[0]].append(word)
    return dict(groups)
```

---

## Day 4 — 数学逻辑

### 题目1:质数列表
> 给一个整数 n,返回所有小于等于 n 的质数列表。

```python
def primes_up_to(n):
    pass

print(primes_up_to(20))   # [2, 3, 5, 7, 11, 13, 17, 19]
print(primes_up_to(1))    # []
print(primes_up_to(2))    # [2]
print(primes_up_to(0))    # []
```

**参考答案:**
```python
def primes_up_to(n):
    def is_prime(num):
        if num < 2: return False
        for i in range(2, int(num**0.5) + 1):
            if num % i == 0: return False
        return True
    return [x for x in range(2, n+1) if is_prime(x)]
```

---

### 题目2:数字的各位数字之积
> 给一个正整数,返回各位数字的乘积。

```python
def digit_product(n):
    pass

print(digit_product(234))    # 24  (2*3*4)
print(digit_product(999))    # 729
print(digit_product(10))     # 0   (1*0)
print(digit_product(5))      # 5
```

**参考答案:**
```python
def digit_product(n):
    result = 1
    for d in str(n):
        result *= int(d)
    return result
```

---

### 题目3:FizzBuzz 变体
> 给一个数组,把每个数字替换:能被3整除换成"Fizz",能被5整除换成"Buzz",都能被整除换成"FizzBuzz",否则保留原数字(字符串形式)。

```python
def fizzbuzz_list(nums):
    pass

print(fizzbuzz_list([1,3,5,15,7]))
# ['1', 'Fizz', 'Buzz', 'FizzBuzz', '7']
print(fizzbuzz_list([]))
# []
```

**参考答案:**
```python
def fizzbuzz_list(nums):
    result = []
    for n in nums:
        if n % 15 == 0:
            result.append("FizzBuzz")
        elif n % 3 == 0:
            result.append("Fizz")
        elif n % 5 == 0:
            result.append("Buzz")
        else:
            result.append(str(n))
    return result
```

---

## Day 5 — 排序 & 双指针

### 题目1:自定义排序
> 给一个学生列表(名字、分数),先按分数降序排,分数相同按名字升序排。

```python
def rank_students(students):
    pass

students = [("Alice",85), ("Bob",92), ("Charlie",85), ("Dave",70)]
print(rank_students(students))
# [('Bob', 92), ('Alice', 85), ('Charlie', 85), ('Dave', 70)]
```

**参考答案:**
```python
def rank_students(students):
    return sorted(students, key=lambda x: (-x[1], x[0]))
```

---

### 题目2:找最长无重复子串的长度
> 给一个字符串,找出最长不含重复字符的子串长度。

```python
def longest_unique_substring(s):
    pass

print(longest_unique_substring("abcabcbb"))  # 3 ("abc")
print(longest_unique_substring("bbbbb"))     # 1 ("b")
print(longest_unique_substring("pwwkew"))    # 3 ("wke")
print(longest_unique_substring(""))          # 0
```

**参考答案:**
```python
def longest_unique_substring(s):
    seen = {}
    max_len = 0
    left = 0
    for right, char in enumerate(s):
        if char in seen and seen[char] >= left:
            left = seen[char] + 1
        seen[char] = right
        max_len = max(max_len, right - left + 1)
    return max_len
```

---

### 题目3:合并两个有序数组
> 给两个升序数组,合并成一个升序数组。

```python
def merge_sorted(a, b):
    pass

print(merge_sorted([1,3,5], [2,4,6]))    # [1,2,3,4,5,6]
print(merge_sorted([], [1,2,3]))          # [1,2,3]
print(merge_sorted([1,2,3], []))          # [1,2,3]
print(merge_sorted([-1,0], [-2,1]))       # [-2,-1,0,1]
```

**参考答案:**
```python
def merge_sorted(a, b):
    return sorted(a + b)

# 进阶版(双指针,更高效):
def merge_sorted_v2(a, b):
    result = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i]); i += 1
        else:
            result.append(b[j]); j += 1
    return result + a[i:] + b[j:]
```

---

## Day 6 — 栈 & 队列

### 题目1:括号匹配
> 给一个只包含括号的字符串,判断括号是否匹配。

```python
def is_valid_brackets(s):
    pass

print(is_valid_brackets("()[]{}"))   # True
print(is_valid_brackets("([)]"))     # False
print(is_valid_brackets("{[]}"))     # True
print(is_valid_brackets(""))         # True
print(is_valid_brackets("]"))        # False
print(is_valid_brackets("("))        # False
```

**参考答案:**
```python
def is_valid_brackets(s):
    stack = []
    mapping = {")": "(", "}": "{", "]": "["}
    for char in s:
        if char in mapping:
            top = stack.pop() if stack else "#"
            if mapping[char] != top:
                return False
        else:
            stack.append(char)
    return not stack
```

---

### 题目2:用栈实现队列
> 只用两个栈,实现一个队列(先进先出)。

```python
class MyQueue:
    def __init__(self):
        pass

    def push(self, x):
        pass

    def pop(self):
        pass

    def peek(self):
        pass

    def empty(self):
        pass

q = MyQueue()
q.push(1); q.push(2); q.push(3)
print(q.peek())   # 1
print(q.pop())    # 1
print(q.pop())    # 2
print(q.empty())  # False
```

**参考答案:**
```python
class MyQueue:
    def __init__(self):
        self.in_stack = []
        self.out_stack = []

    def push(self, x):
        self.in_stack.append(x)

    def _transfer(self):
        if not self.out_stack:
            while self.in_stack:
                self.out_stack.append(self.in_stack.pop())

    def pop(self):
        self._transfer()
        return self.out_stack.pop()

    def peek(self):
        self._transfer()
        return self.out_stack[-1]

    def empty(self):
        return not self.in_stack and not self.out_stack
```

---

## Day 7 — 综合复盘题

### 题目1:第一个不重复的字符
> 给一个字符串,找出第一个不重复的字符并返回其下标。不存在返回 -1。

```python
def first_unique_char(s):
    pass

print(first_unique_char("leetcode"))    # 0 ('l')
print(first_unique_char("loveleetcode")) # 2 ('v')
print(first_unique_char("aabb"))        # -1
print(first_unique_char(""))            # -1
```

**参考答案:**
```python
from collections import Counter

def first_unique_char(s):
    count = Counter(s)
    for i, ch in enumerate(s):
        if count[ch] == 1:
            return i
    return -1
```

---

### 题目2:乘积最大的三个数
> 给一个整数数组,返回乘积最大的三个数之积。数组长度至少为 3。

```python
def max_product_of_three(nums):
    pass

print(max_product_of_three([1,2,3,4]))       # 24
print(max_product_of_three([-10,-10,1,3,2])) # 300 (-10*-10*3)
print(max_product_of_three([-1,-2,-3]))      # -6
```

**参考答案:**
```python
def max_product_of_three(nums):
    nums.sort()
    # 最大的三个数之积 vs 最小的两个(可能负负得正)× 最大的一个
    return max(nums[-1]*nums[-2]*nums[-3], nums[0]*nums[1]*nums[-1])
```

---

## Day 8 — 二维数组

### 题目1:矩阵对角线之和
> 给一个 n×n 矩阵,返回主对角线和副对角线之和(中心元素只算一次)。

```python
def diagonal_sum(matrix):
    pass

print(diagonal_sum([[1,2,3],[4,5,6],[7,8,9]]))   # 25 (1+5+9+3+7)
print(diagonal_sum([[1,1],[1,1]]))               # 4
print(diagonal_sum([[5]]))                        # 5
```

**参考答案:**
```python
def diagonal_sum(matrix):
    n = len(matrix)
    total = 0
    for i in range(n):
        total += matrix[i][i]           # 主对角线
        total += matrix[i][n-1-i]       # 副对角线
    if n % 2 == 1:
        total -= matrix[n//2][n//2]     # 中心元素减去一次(加了两次)
    return total
```

---

### 题目2:搜索二维矩阵
> 给一个每行升序、每行第一个数大于上一行最后一个数的矩阵,判断目标值是否存在。

```python
def search_matrix(matrix, target):
    pass

matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]]
print(search_matrix(matrix, 3))    # True
print(search_matrix(matrix, 13))   # False
print(search_matrix([], 1))        # False
```

**参考答案:**
```python
def search_matrix(matrix, target):
    if not matrix or not matrix[0]:
        return False
    rows, cols = len(matrix), len(matrix[0])
    left, right = 0, rows * cols - 1
    while left <= right:
        mid = (left + right) // 2
        val = matrix[mid // cols][mid % cols]
        if val == target: return True
        elif val < target: left = mid + 1
        else: right = mid - 1
    return False
```

---

## Day 9 — 递归

### 题目1:展平嵌套列表
> 给一个可以无限嵌套的列表,展平成一维列表。

```python
def flatten(lst):
    pass

print(flatten([1,[2,[3,4]],5]))          # [1,2,3,4,5]
print(flatten([[1,2],[3,[4,[5]]]]))      # [1,2,3,4,5]
print(flatten([]))                       # []
print(flatten([1,2,3]))                  # [1,2,3]
```

**参考答案:**
```python
def flatten(lst):
    result = []
    for item in lst:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result
```

---

### 题目2:汉诺塔步骤数
> 给 n 个圆盘的汉诺塔,返回最少需要多少步。

```python
def hanoi_steps(n):
    pass

print(hanoi_steps(1))   # 1
print(hanoi_steps(2))   # 3
print(hanoi_steps(3))   # 7
print(hanoi_steps(10))  # 1023
```

**参考答案:**
```python
def hanoi_steps(n):
    if n == 1:
        return 1
    return 2 * hanoi_steps(n-1) + 1
# 规律:2^n - 1,也可以直接 return 2**n - 1
```

---

## Day 10 — 综合强化

### 题目1:字符串压缩
> 给一个字符串,用"字符+出现次数"压缩。如果压缩后不比原字符串短,返回原字符串。

```python
def compress_string(s):
    pass

print(compress_string("aabcccdddd"))   # "a2b1c3d4"
print(compress_string("abc"))          # "abc"(压缩后更长)
print(compress_string("aabb"))         # "aabb"(一样长,返回原字符串)
print(compress_string(""))             # ""
```

**参考答案:**
```python
def compress_string(s):
    if not s:
        return ""
    result = []
    count = 1
    for i in range(1, len(s)):
        if s[i] == s[i-1]:
            count += 1
        else:
            result.append(s[i-1] + str(count))
            count = 1
    result.append(s[-1] + str(count))
    compressed = "".join(result)
    return compressed if len(compressed) < len(s) else s
```

---

### 题目2:找所有和为目标值的二元组
> 给一个整数数组和目标值,找出所有和等于目标值的不重复二元组。

```python
def find_pairs(nums, target):
    pass

print(find_pairs([1,2,3,4,5,6], 7))    # [(1,6),(2,5),(3,4)]
print(find_pairs([1,1,2,3], 4))        # [(1,3)]
print(find_pairs([], 5))               # []
print(find_pairs([3,3], 6))            # [(3,3)]
```

**参考答案:**
```python
def find_pairs(nums, target):
    seen = set()
    used = set()
    result = []
    for n in nums:
        complement = target - n
        if complement in seen and (min(n, complement), max(n, complement)) not in used:
            pair = (min(n, complement), max(n, complement))
            result.append(pair)
            used.add(pair)
        seen.add(n)
    return sorted(result)
```

---

## Day 11 — 模拟考试①

### 题目1:字母异位词
> 给两个字符串,判断是否是字母异位词(字母相同但顺序不同)。

```python
def is_anagram(s, t):
    pass

print(is_anagram("listen", "silent"))   # True
print(is_anagram("hello", "world"))     # False
print(is_anagram("", ""))              # True
print(is_anagram("ab", "a"))           # False
```

**参考答案:**
```python
from collections import Counter

def is_anagram(s, t):
    return Counter(s) == Counter(t)
```

---

### 题目2:多数元素
> 给一个数组,找出出现次数超过 n//2 的元素(保证存在)。

```python
def majority_element(nums):
    pass

print(majority_element([3,2,3]))          # 3
print(majority_element([2,2,1,1,1,2,2]))  # 2
print(majority_element([1]))              # 1
```

**参考答案:**
```python
from collections import Counter

def majority_element(nums):
    count = Counter(nums)
    return max(count, key=count.get)

# Boyer-Moore 投票算法(进阶,O(1)空间):
def majority_element_v2(nums):
    candidate, count = None, 0
    for n in nums:
        if count == 0:
            candidate = n
        count += (1 if n == candidate else -1)
    return candidate
```

---

### 题目3:完全平方数
> 给一个正整数,判断是否是完全平方数,不能用 sqrt。

```python
def is_perfect_square(n):
    pass

print(is_perfect_square(16))   # True
print(is_perfect_square(14))   # False
print(is_perfect_square(1))    # True
print(is_perfect_square(25))   # True
```

**参考答案:**
```python
def is_perfect_square(n):
    left, right = 1, n
    while left <= right:
        mid = (left + right) // 2
        if mid * mid == n:
            return True
        elif mid * mid < n:
            left = mid + 1
        else:
            right = mid - 1
    return False
```

---

## Day 12 — 模拟考试②

### 题目1:最长公共前缀
> 给一个字符串数组,找出所有字符串的最长公共前缀。

```python
def longest_common_prefix(strs):
    pass

print(longest_common_prefix(["flower","flow","flight"]))  # "fl"
print(longest_common_prefix(["dog","racecar","car"]))     # ""
print(longest_common_prefix([]))                          # ""
print(longest_common_prefix(["alone"]))                   # "alone"
```

**参考答案:**
```python
def longest_common_prefix(strs):
    if not strs:
        return ""
    prefix = strs[0]
    for s in strs[1:]:
        while not s.startswith(prefix):
            prefix = prefix[:-1]
            if not prefix:
                return ""
    return prefix
```

---

### 题目2:有效的回文数
> 给一个整数,判断是否是回文数。不能转成字符串。

```python
def is_palindrome_number(x):
    pass

print(is_palindrome_number(121))    # True
print(is_palindrome_number(-121))   # False(负数不是回文)
print(is_palindrome_number(10))     # False
print(is_palindrome_number(0))      # True
```

**参考答案:**
```python
def is_palindrome_number(x):
    if x < 0 or (x != 0 and x % 10 == 0):
        return False
    reversed_half = 0
    while x > reversed_half:
        reversed_half = reversed_half * 10 + x % 10
        x //= 10
    return x == reversed_half or x == reversed_half // 10
```

---

## Day 13-14 — 综合挑战题

### 题目1:最长回文子串
```python
def longest_palindrome(s):
    pass

print(longest_palindrome("babad"))   # "bab" 或 "aba"
print(longest_palindrome("cbbd"))    # "bb"
print(longest_palindrome("a"))       # "a"
print(longest_palindrome(""))        # ""
```

**参考答案:**
```python
def longest_palindrome(s):
    if not s:
        return ""
    start, end = 0, 0
    for i in range(len(s)):
        for l, r in [(i, i), (i, i+1)]:   # 奇数和偶数回文
            while l >= 0 and r < len(s) and s[l] == s[r]:
                if r - l > end - start:
                    start, end = l, r
                l -= 1; r += 1
    return s[start:end+1]
```

---

### 题目2:接雨水(经典压轴题)
> 给一个数组代表柱子高度,计算能接多少雨水。

```python
def trap_rain(height):
    pass

print(trap_rain([0,1,0,2,1,0,1,3,2,1,2,1]))  # 6
print(trap_rain([4,2,0,3,2,5]))               # 9
print(trap_rain([]))                           # 0
print(trap_rain([1,2,3]))                      # 0
```

**参考答案:**
```python
def trap_rain(height):
    if not height:
        return 0
    left, right = 0, len(height) - 1
    left_max = right_max = 0
    water = 0
    while left < right:
        if height[left] < height[right]:
            if height[left] >= left_max:
                left_max = height[left]
            else:
                water += left_max - height[left]
            left += 1
        else:
            if height[right] >= right_max:
                right_max = height[right]
            else:
                water += right_max - height[right]
            right -= 1
    return water
```

---

**共 25 道题,覆盖 14 天全部知识点。** 每道题都要:
1. 先自己写,不看答案
2. 测试所有边界用例
3. 看答案对比思路


part 3