Compare commits

...

2 Commits

Author SHA1 Message Date
c97e452c44 Add 2026.07.15 session 2026-07-14 20:44:18 -04:00
953ce7f2cb Implement a sample solution which passes all test cases 2026-07-14 19:24:04 -04:00
5 changed files with 17865 additions and 11 deletions

View File

@@ -84,17 +84,95 @@ class RedBlackTree:
elif root.value < value: elif root.value < value:
self.delete(value, root.right, root) self.delete(value, root.right, root)
def rebalance_from_just_inserted(self, node: Node): def rebalance_from_just_inserted(self, node: Node | None):
# This is what you'll be implementing. if node is None:
# return
# By the time this is called, `node` has already been inserted like a
# normal BST node, colored red, and had its `parent` pointer set (see parent = node.parent
# insert()). Your job is to restore the red-black properties by if parent is not None and not parent.is_red:
# rebalancing the subtree around `node`. return
# elif parent is None:
# Rebalancing is only needed when node.parent is red. Remember to keep node.is_red = False
# the root black at the end. return
pass
grandparent = parent.parent
if grandparent is None:
return
uncle = grandparent.right if grandparent.left == parent else grandparent.left
if uncle is not None and uncle.is_red:
uncle.is_red = False
parent.is_red = False
grandparent.is_red = True
self.rebalance_from_just_inserted(grandparent)
return
if grandparent.left == parent and parent.right == node:
node, parent = parent, self.rotate_left(parent)
elif grandparent.right == parent and parent.left == node:
node, parent = parent, self.rotate_right(parent)
new_grandparent: Node | None = None
if grandparent.left == parent and parent.left == node:
new_grandparent = self.rotate_right(grandparent)
elif grandparent.right == parent and parent.right == node:
new_grandparent = self.rotate_left(grandparent)
if grandparent == self.root and new_grandparent is not None:
self.root = new_grandparent
self.root.is_red = False
grandparent.is_red = True
def rotate_left(self, node: Node) -> Node:
if node.right is None:
return node
original_parent = node.parent
new_parent = node.right
new_right_child = node.right.left
node.right = new_right_child
if new_right_child is not None:
new_right_child.parent = node
new_parent.left = node
node.parent = new_parent
new_parent.parent = original_parent
if original_parent is not None:
if original_parent.left == node:
original_parent.left = new_parent
elif original_parent.right == node:
original_parent.right = new_parent
return new_parent
def rotate_right(self, node: Node) -> Node:
if node.left is None:
return node
original_parent = node.parent
new_parent = node.left
new_left_child = node.left.right
node.left = new_left_child
if new_left_child is not None:
new_left_child.parent = node
new_parent.right = node
node.parent = new_parent
new_parent.parent = original_parent
if original_parent is not None:
if original_parent.left == node:
original_parent.left = new_parent
elif original_parent.right == node:
original_parent.right = new_parent
return new_parent
def visualize(self) -> str: def visualize(self) -> str:
# renders the tree top-down with the root on top and branches # renders the tree top-down with the root on top and branches

View File

@@ -0,0 +1,70 @@
## Fundamentals
- A *node* or *vertex* contains a data point
- An *edge* is what connects one node to another
A graph is just a collection of vertices and edges.
> [!QUESTION] What is a real-life example of a simple graph with only vertices and edges?
Some additional properties we can put on a graph:
- A *weight* is a numerical value that can be assigned to an edge
- We can also assign a *direction* to an edge, such that it only points from one node to another, not the other way around
We can, of course, combine both of these properties too.
> [!QUESTION] What's something we can model with weights in a graph? What about with directional edges?
Going forward, we'll use $V$ to represent the number of vertices in a graph, and $E$ to represent the number of edges.
## Representing a graph
The *adjacency list* stores a list of connected vertices for each node, and it can fit in a dictionary or hash map structure.
```
1 -> 2, 4
2 -> 1, 3
3 -> 2
4 -> 1
```
> [!QUESTION] How would you draw out this graph?
> [!QUESTION] What would this mapping look like if we wanted to add weights? What about directional edges?
The *adjacency matrix* is a 2D array where each position `arr[x][y]` represents an edge, and `x` and `y` each represent a node.
```
[
[0, 1, 0, 1],
[1, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]
]
```
> [!QUESTION] How would you draw out this graph? What would it look like as an adjacency list?
> [!QUESTION] How do we add weights and/or directional edges to this graph?
## Categorizing graphs
We say a graph is *directed and acyclic*, or a *directed acyclic graph (DAG)*, if there are no cycles formed using the directional edges.
> [!QUESTION] What's something we can model with a DAG?
> [!QUESTION] What's another data structure we went over that also classifies as a DAG?
A graph is *dense* if $E$ is closer to $V^2$, and *sparse* if $E$ is closer to $V$.
> [!QUESTION] What's the implication for the graph if $E$ is closer to $V^2$, i.e. how is it different compared to a sparse graph?
> [!QUESTION] What's the maximum number of edges we can have in a graph with no self-loops, relative to the number of vertices $V$?
A graph can contain *self-loops* (a loop from a vertex to itself). A graph can also have *multiple edges* going from one vertex to another.
> [!QUESTION] How do we represent a self-loop using an adjacency matrix?
Finally, a graph is *connected* if every vertex is reachable from every other vertex.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

View File

@@ -0,0 +1,18 @@
## Outline
- Go over the homework
- Go over the basics of graphs, see [Introduction to graphs](./graphs-intro.md)
![Graphs introduction whiteboard](./graphs.png)
To open the `.excalidraw` file:
- Launch https://excalidraw.com
- Click the top left menu, then select "Open"
- Select the `.excalidraw` file from the file picker
## Assignment
- Try to complete the red-black implementation from last week
- Complete the exercise for the 2D array (see the picture)