University of Waterloo(滑铁卢大学)是全球最顶尖的 CS 本科项目之一,以极强的 Co-op 项目著称(Google、微软、Shopify 每年大量招收 UWaterloo 实习生)。但 UWaterloo CS 的课程也出了名的难——不只是内容本身,而是评分严格、竞争激烈。
CS136 和 MATH135 是 UWaterloo CS 荣誉专业(Computer Science Honours)第一年的两门核心课,也是拦住很多同学的"第一关"。
UWaterloo 成绩体系
UWaterloo 使用百分制,但 CS 专业有严格的 GPA 要求维持条件:
| 百分制 | 字母 | 4.0 GPA 换算 |
|---|---|---|
| 90–100 | A+ | 4.0 |
| 85–89 | A | 4.0 |
| 80–84 | A- | 3.7 |
| 77–79 | B+ | 3.3 |
| 73–76 | B | 3.0 |
| 70–72 | B- | 2.7 |
| 60–69 | C+ / C | 2.3–2.0 |
UWaterloo CS 荣誉专业保留要求:累计 GPA 通常需要维持 60%(C+)以上,否则有被降专业的风险。
CS136 核心内容
CS136 是 CS135(用 Racket 教函数式编程)的延续,后半段引入 C 语言,核心是数据抽象与算法设计。
第一部分:Racket(延续 CS135)
Racket 是 Scheme 的一个方言,函数式编程语言。CS135 的思想在 CS136 前期继续强化:
;; 递归计算列表长度
(define (my-length lst)
(cond [(empty? lst) 0]
[else (+ 1 (my-length (rest lst)))]))
;; 尾递归版本(更高效)
(define (my-length/tr lst acc)
(cond [(empty? lst) acc]
[else (my-length/tr (rest lst) (+ acc 1))]))
CS136 新增:高阶函数和抽象
;; map 的手动实现
(define (my-map f lst)
(cond [(empty? lst) '()]
[else (cons (f (first lst))
(my-map f (rest lst)))]))
;; filter 的手动实现
(define (my-filter pred lst)
(cond [(empty? lst) '()]
[(pred (first lst))
(cons (first lst) (my-filter pred (rest lst)))]
[else (my-filter pred (rest lst))]))
第二部分:C 语言基础
CS136 后半段从 Racket 过渡到 C,这对从未接触 C 的同学是个跳跃:
C 与 Racket 的关键区别:
| 方面 | Racket(函数式) | C(命令式) |
|---|---|---|
| 内存管理 | 自动垃圾回收 | 手动 malloc/free |
| 变量 | 不可变 | 可变,有类型 |
| 循环 | 递归 | for/while |
| 数组 | 列表(linked list) | 连续内存块 |
C 基础语法:
#include <stdio.h>
#include <stdlib.h>
// 函数:计算数组元素之和
int array_sum(int arr[], int len) {
int sum = 0;
for (int i = 0; i < len; i++) {
sum += arr[i];
}
return sum;
}
int main(void) {
int nums[] = {1, 2, 3, 4, 5};
int result = array_sum(nums, 5);
printf("Sum: %d\n", result); // Sum: 15
return 0;
}
指针(Pointer)——CS136 最难的部分:
int x = 10;
int *p = &x; // p 存储 x 的地址
*p = 20; // 通过指针修改 x 的值
printf("%d\n", x); // 输出 20
// 动态内存分配
int *arr = malloc(5 * sizeof(int)); // 分配 5 个 int 的空间
arr[0] = 1; arr[1] = 2; // 使用
free(arr); // 用完必须释放!
常见内存错误(CS136 期末考查重点):
| 错误类型 | 说明 |
|---|---|
| Memory Leak | malloc 后忘记 free |
| Dangling Pointer | free 后继续使用指针 |
| Buffer Overflow | 写入数组越界 |
| Use after Free | free 后访问内存 |
第三部分:算法复杂度
CS136 要求能分析函数的时间复杂度:
| 复杂度 | 名称 | 例子 |
|---|---|---|
| O(1) | 常数 | 数组索引 |
| O(log n) | 对数 | 二分搜索 |
| O(n) | 线性 | 线性搜索 |
| O(n log n) | 线性对数 | 归并排序 |
| O(n²) | 二次 | 冒泡排序 |
MATH135 核心内容
MATH135 Algebra for Honours Mathematics 是数论+代数入门,强调严格数学证明。
第一部分:整除性与 GCD
整除定义:$a | b$ 表示 $b = ka$(a 整除 b)
欧几里得算法(GCD):
$$\gcd(a, b) = \gcd(b, a \bmod b) \quad \text{直到} ; b = 0$$
扩展欧几里得算法:找到整数 $x, y$ 使得 $ax + by = \gcd(a, b)$(贝祖定理)
第二部分:模运算(Modular Arithmetic)
$$a \equiv b \pmod{n} \iff n \mid (a - b)$$
费马小定理(MATH135 必知):若 $p$ 为素数且 $\gcd(a, p) = 1$,则:
$$a^{p-1} \equiv 1 \pmod{p}$$
中国剩余定理(CRT):若 $m_1, m_2, \ldots, m_k$ 两两互素,则方程组: $$x \equiv a_1 \pmod{m_1}, ; x \equiv a_2 \pmod{m_2}, \ldots$$ 有唯一解(模 $m_1 m_2 \cdots m_k$)。
第三部分:证明技巧
MATH135 的核心挑战是写出严格的数学证明:
常用证明方法:
| 方法 | 适用情况 |
|---|---|
| 直接证明(Direct Proof) | 从假设直接推结论 |
| 反证法(Proof by Contradiction) | 假设结论为假,推出矛盾 |
| 数学归纳法(Induction) | 证明对所有自然数成立 |
| 构造证明(Constructive) | 找到满足条件的例子 |
证明格式示例(MATH135 标准):
题目:证明若 $n^2$ 为偶数,则 $n$ 为偶数。
证明(反证法):
假设 n² 为偶数但 n 为奇数。
若 n 为奇数,则 n = 2k+1(某整数 k)。
则 n² = (2k+1)² = 4k² + 4k + 1 = 2(2k²+2k) + 1,
这是奇数——与 n² 为偶数矛盾。
因此 n 必为偶数。 □
UWaterloo CS 备考建议
- CS136:最难的是 C 指针和内存管理——用 Valgrind 检测内存错误,大量练习 malloc/free
- MATH135:证明格式一分不能少——从假设开始,每步给出理由,用 □ 结束
- 作业质量:UWaterloo 作业评分严格,不能只有答案,必须有完整过程
- 时间管理:UWaterloo CS 的作业和 midterm 密度很高,提前一周开始准备
相关资源:
