Harvard CS50 is the most-watched computer science course on the internet. David Malan's lectures have introduced millions of people to programming, algorithms, and the foundational ideas of software. The official CS50 website offers problem sets and a full curriculum, but what most students struggle with is converting two-hour video lectures into something they can actually study from.
These Harvard CS50 notes are built for that exact purpose. Every week is covered — from the very first Scratch lecture through Python, SQL, and web development. If you are working through the course and need a reference you can review in 20 minutes before a problem set, this is it.
The official course lives at cs50.harvard.edu. These notes are a companion, not a replacement — watch the lectures, then use this guide to consolidate what you learned.
Week 0: Scratch and Computational Thinking
CS50 begins not with a programming language but with a concept: computational thinking. Malan's central argument is that programming is really problem decomposition — breaking a problem into smaller, solvable pieces, then expressing those steps precisely.
Key vocabulary from Week 0:
- Algorithm — a step-by-step procedure for solving a problem. The phone book example: searching page by page is O(n), tearing the book in half repeatedly is O(log n). Malan uses this to introduce efficiency before a single line of code is written.
- Pseudocode — writing out logic in plain English before translating it into a programming language. CS50 emphasizes this heavily: think first, code second.
- Functions, conditions, loops, variables — the four building blocks introduced in Scratch that map directly to every language you will ever learn.
- Events and threads — Scratch's broadcast system is your first exposure to event-driven programming and the idea that multiple things can run simultaneously.
Scratch is not a toy. The animations, games, and interactive stories built in Scratch require the same logical reasoning as C or Python. Students who skip Week 0 because "it looks like a kids' course" often struggle more with later weeks because they skipped the conceptual foundation.
Problem Set 0 asks you to build something in Scratch that uses at minimum: one condition, one loop, one variable, and one custom block. The custom block is Scratch's version of a function — this is intentional.
Week 1: C — The Language Underneath Everything
Week 1 is where CS50 becomes demanding. C is verbose, unforgiving, and forces you to manage things that Python and JavaScript handle automatically. This is exactly why Malan teaches it first.
Core concepts:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string name = get_string("What's your name? ");
printf("hello, %s\n", name);
}
The #include lines are header files — libraries that give your program access to functions someone else wrote. cs50.h is a custom library Malan's team built to make C more approachable; get_string, get_int, and get_float are from this library.
Critical Week 1 concepts:
- Data types in C —
int(integers),float(decimals),char(single character),string(text, technically a char array),bool(true/false). Unlike Python, you must declare the type of every variable. - Format specifiers —
%ifor integers,%ffor floats,%sfor strings,%cfor chars. Getting these wrong produces garbage output or a crash. - Integer overflow — if an
intexceeds its maximum value (~2.1 billion for a 32-bit signed int), it wraps around to a large negative number. This is not theoretical: the Year 2038 problem is integer overflow in Unix timestamps. - Truncation — dividing two integers in C produces an integer.
5 / 2gives2, not2.5. You must cast to float:(float) 5 / 2. - Loops —
for,while,do-while. Know when each is appropriate.do-whileruns the body at least once before checking the condition; useful for prompting user input. - Conditionals —
if,else if,else, andswitch. Theswitchstatement is cleaner than a long chain ofif/else ifwhen testing a single variable against multiple values.
Compilation pipeline (not just "compile and run"):
- Preprocessing — handles
#includeand#definedirectives - Compiling — converts C to assembly language
- Assembling — converts assembly to machine code (binary)
- Linking — combines your object file with library files
make and clang hide all of this. Understanding what actually happens prepares you for Week 8 and later courses.
Week 2: Arrays, Strings, and Command-Line Arguments
Week 2 digs into how data is actually stored in memory. This is where CS50 starts to feel different from most introductory courses.
Arrays:
An array is a contiguous block of memory holding values of the same type. int scores[3] allocates space for three integers, side-by-side in memory. Array indices start at 0. Accessing scores[3] on a 3-element array is undefined behavior — C will not warn you; it will either crash or silently read whatever happens to be in memory at that address.
Strings as char arrays:
In C, a string is an array of char values terminated by a null character \0. The string "hello" occupies 6 bytes: h, e, l, l, o, \0. This is why string length functions iterate until they hit \0 — there is no length stored anywhere.
string s = "hello";
// s[0] = 'h', s[1] = 'e', ..., s[5] = '\0'
Command-line arguments:
int main(int argc, string argv[])
argc is the argument count (including the program name). argv is an array of strings. argv[0] is always the program name; argv[1] is the first user argument. Always check argc before accessing argv[1] — if the user runs the program with no arguments, argv[1] is undefined.
Cryptography problem set (Caesar/Substitution): These problems require looping over every character of a string, checking if it is alphabetic, and shifting it. The key insight is using ASCII values: 'A' is 65, 'a' is 97. Shifting a character means doing arithmetic on its ASCII value, then converting back.
Week 3: Algorithms — Search and Sort
Week 3 is where CS50 introduces algorithm analysis formally. Malan covers linear search, binary search, bubble sort, selection sort, merge sort, and introduces Big O notation.
Big O notation — what it actually means:
Big O describes how running time grows as input size grows. It is an upper bound, not an exact measurement.
| Notation | Name | Example |
|---|---|---|
| O(1) | Constant | Array index lookup |
| O(log n) | Logarithmic | Binary search |
| O(n) | Linear | Linear search |
| O(n log n) | Log-linear | Merge sort |
| O(n²) | Quadratic | Bubble/selection sort |
Ω (Omega) and Θ (Theta): Malan also introduces lower bounds (Ω) and tight bounds (Θ). Merge sort is Θ(n log n) — its best and worst case are the same. Bubble sort is O(n²) worst case but Ω(n) best case (if already sorted and you check for swaps).
Sorting algorithms:
- Bubble sort — repeatedly swap adjacent elements if out of order. Simple but O(n²). Each pass "bubbles" the largest unsorted element to the end.
- Selection sort — find the minimum element in the unsorted portion, swap it into position. Also O(n²), but performs fewer swaps.
- Merge sort — divide array in half recursively until you have single elements, then merge sorted halves. O(n log n). Requires extra memory. This is the first recursive algorithm most students encounter.
Recursion: A function that calls itself. Every recursive solution has a base case (terminates) and a recursive case (calls itself with a simpler input). The classic example is factorial: factorial(n) = n * factorial(n-1), base case factorial(0) = 1.
Week 4: Memory, Pointers, and Hexadecimal
Week 4 is the hardest week for most students. Pointers are the concept that separates those who truly understand C from those who memorized syntax.
Hexadecimal:
Memory addresses are conventionally written in hexadecimal (base 16). Digits: 0-9, then A-F. 0x prefix marks hex literals. Each hex digit represents 4 bits, so two hex digits (like FF) represent one byte. Understanding hex is essential for reading debugger output, memory dumps, and network protocols.
Pointers:
A pointer is a variable that stores a memory address.
int n = 50;
int *p = &n; // p holds the address of n
printf("%i\n", *p); // dereference: prints 50
printf("%p\n", p); // prints the address, e.g. 0x7ffee4b4d5c
&— "address of" operator. Gets the memory address of a variable.*— two uses: (1) declare a pointer variable (int *p), (2) dereference a pointer (*pgives the value at that address).
Dynamic memory allocation:
int *x = malloc(4); // allocate 4 bytes on the heap
free(x); // release it when done
malloc returns a pointer to allocated heap memory (or NULL if allocation fails — always check). free releases it. Forgetting to free memory is a memory leak. Freeing memory twice is a double free and usually causes a crash. Accessing freed memory is a use-after-free bug.
Stack vs. heap:
- Stack — local variables, function call frames. Automatically managed. Fixed size.
- Heap — dynamically allocated memory. You manage it. Can be large but fragmented.
Valgrind: CS50 introduces this tool to detect memory errors. Running valgrind ./program reports leaks, invalid reads/writes, and use-after-free bugs. Getting a clean Valgrind output is part of the problem set grade.
Week 5: Data Structures
Week 5 is where computer science becomes beautiful. Malan covers linked lists, trees, hash tables, and tries — data structures that underpin virtually every non-trivial software system.
Linked lists:
A linked list is a sequence of nodes, where each node contains a value and a pointer to the next node. Unlike arrays, linked lists do not require contiguous memory and can grow dynamically.
typedef struct node {
int number;
struct node *next;
} node;
Trade-offs vs. arrays: insertion/deletion at the front is O(1) with a linked list vs. O(n) for an array. But random access is O(n) for a linked list vs. O(1) for an array. No data structure is universally better.
Trees:
A binary search tree (BST) stores values such that left child < parent < right child. Search, insertion, and deletion are O(log n) on a balanced tree. An unbalanced tree (e.g., inserting sorted data into a naive BST) degenerates to O(n) — effectively a linked list.
Hash tables:
A hash table maps keys to values using a hash function. A good hash function distributes keys uniformly. Collisions (two keys hashing to the same bucket) are resolved by chaining (linked list at each bucket) or open addressing. Average case O(1) lookup; worst case O(n) if everything collides.
Tries:
A trie stores strings such that each node represents one character. Looking up a word takes O(k) time where k is the word length — independent of how many words are stored. Memory-heavy but extremely fast for dictionary lookups. CS50's Speller problem set is designed around this.
Week 6: Python — Transition from C
After four weeks of C, Python feels like a revelation. Week 6 is largely a translation exercise — every concept from Weeks 1-5 in Python.
What Python handles automatically that C did not:
- Memory management (garbage collector)
- Type inference (no type declarations)
- Dynamic arrays (Python lists grow as needed)
- String handling (strings are objects, not char arrays)
- No null terminators, no pointers, no
malloc/free
Idiomatic Python for CS50 students:
# CS50's get_string equivalent
name = input("What's your name? ")
print(f"hello, {name}")
# Sorting (Tim sort, O(n log n))
numbers = [3, 1, 4, 1, 5, 9]
numbers.sort() # in-place
sorted_numbers = sorted(numbers) # returns new list
# File I/O
with open("names.csv") as file:
reader = csv.DictReader(file)
for row in reader:
print(row["name"])
The with statement handles file closing automatically — no resource leaks.
Python data structures to know:
list— dynamic array, O(1) append, O(n) insert at arbitrary positiondict— hash table, O(1) average lookupset— hash table of unique values, O(1) membership testtuple— immutable list
If you are continuing toward machine learning after CS50, see Andrew Ng's ML course notes — Python and NumPy are central.
Week 7: SQL and Databases
Week 7 introduces SQL through SQLite. The lecture covers relational databases, CRUD operations, indexes, and common vulnerabilities.
Core SQL syntax:
-- Select
SELECT first, last FROM students WHERE house = 'Gryffindor' ORDER BY last;
-- Insert
INSERT INTO students (first, last, house, birth) VALUES ('Harry', 'Potter', 'Gryffindor', 1980);
-- Update
UPDATE students SET house = 'Slytherin' WHERE first = 'Draco';
-- Delete
DELETE FROM students WHERE first = 'Harry' AND last = 'Potter';
Indexes: Without an index, a SELECT with a WHERE clause scans every row — O(n). An index on the WHERE column allows B-tree lookup — O(log n). Creating indexes has costs: extra storage, slower writes. CS50 teaches CREATE INDEX and explains the trade-off.
SQL injection: The single most important security concept in Week 7. If user input is concatenated directly into a SQL query, a malicious user can inject SQL code. The fix is parameterized queries (prepared statements), where user input is always treated as data, never as SQL.
# Vulnerable
db.execute(f"SELECT * FROM users WHERE username = '{username}'")
# Safe
db.execute("SELECT * FROM users WHERE username = ?", username)
Week 8 and Beyond: HTML, CSS, Flask, and JavaScript — What Does the Web Track Actually Cover?
Weeks 8-10 pivot from systems programming and algorithms to web development. The tone of the course shifts.
Week 8 — HTML/CSS/HTTP:
- HTTP request/response cycle: client sends a request with method (GET/POST), URL, headers. Server responds with status code, headers, body.
- Status codes: 200 OK, 301 Moved Permanently, 302 Found, 404 Not Found, 500 Internal Server Error.
- HTML structure:
<!DOCTYPE html>,<html>,<head>,<body>. Semantic elements:<header>,<main>,<nav>,<footer>,<article>. - CSS: the box model (content, padding, border, margin). Selectors: element, class (
.class), ID (#id). Specificity rules.
Week 9 — Flask:
Flask is a Python micro-framework for web applications. CS50's Flask introduction covers routing, templates (Jinja2), forms, sessions, and SQLite integration.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
name = request.form.get("name")
return render_template("greet.html", name=name)
return render_template("index.html")
Week 10 — JavaScript and Emoji:
Week 10 covers JavaScript in the browser: DOM manipulation, event listeners, fetch for AJAX requests, and local storage. The lecture traditionally ends with a fun segment on emoji, hence the informal name.
The deeper point of Week 10: the web is fundamentally event-driven. Button clicks, network responses, and timers are all events. Writing clean event-driven code means understanding callbacks, promises, and (in modern JS) async/await.
How to Actually Study CS50 Without Drowning — What Successful Students Do Differently?
CS50 is famous for being hard. Students who complete it successfully tend to share a few habits:
1. Watch the lecture twice. Once for the big picture, once for the details. Many students take notes the second time. Using a tool that auto-generates notes from the YouTube lecture URL before you start the problem set saves significant time.
2. Read the problem set spec before you write any code. The specs are long for a reason. Students who skip straight to coding often implement the wrong thing and have to start over.
3. Use debug50 and printf debugging. CS50 ships with a built-in debugger. But printf debugging — inserting print statements to see what values variables hold — is a skill you will use for the rest of your programming life. Learn both.
4. Do not look at the solutions. The value of CS50 is not the certificate. It is the problem-solving muscle you build by struggling with the problem sets. Students who look up solutions typically can not pass a technical interview six months later.
5. Connect CS50 to what comes next. CS50 is a foundation, not a destination. After finishing, consider MIT 6.034 AI notes for artificial intelligence, or the Stanford CS230 deep learning notes for ML. For a broader map of where to go next, the reverse-engineer college courses guide lays out the paths clearly.
Generating Your Own CS50 Study Notes with AI
Every CS50 lecture is freely available on YouTube. That means you can paste any lecture URL into an AI note-taking tool and get a structured summary, key concept list, and flashcards in seconds — before you even start the problem set.
Students who build this habit — video URL into notes before coding — report significantly better retention. The process forces you to identify what you actually understood vs. what you just watched. The gap between those two is where most exam mistakes live.
For a full walkthrough of this workflow, see the YouTube to notes complete guide.
CS50 is one of the best investments of time a self-learner can make. Finish it, and you will have the foundations to go anywhere in software. These notes are a study companion — use them alongside David Malan's lectures, not instead of them.
Ready to turn any CS50 lecture into structured notes and flashcards automatically? Try Notiq free at notiq.study — paste the YouTube URL and get a full study guide in under a minute.

