Bird
Raised Fist0
DSA Typescriptprogramming~15 mins

Adjacency Matrix Representation in DSA Typescript - Deep Dive

Choose your learning style10 modes available
Overview - Adjacency Matrix Representation
What is it?
An adjacency matrix is a way to represent a graph using a square grid of numbers. Each row and column corresponds to a node in the graph. The value at the intersection shows if there is a connection (edge) between those nodes. This method works well for graphs with a fixed number of nodes.
Why it matters
Without a clear way to represent connections between nodes, it would be hard to analyze or work with networks like social media, maps, or computer networks. The adjacency matrix makes it easy to check if two nodes are connected quickly. Without it, many algorithms would be slower or more complex.
Where it fits
Before learning adjacency matrices, you should understand what graphs are and basic graph terms like nodes and edges. After this, you can learn about other graph representations like adjacency lists and how to use these structures in graph algorithms such as searching or shortest path.
Mental Model
Core Idea
An adjacency matrix is a grid where each cell tells you if two nodes in a graph are connected or not.
Think of it like...
Imagine a classroom seating chart where each student is a node. The chart shows if two students are friends by marking their seats' intersection with a 1 (friends) or 0 (not friends).
    Nodes ->
      0 1 2 3
    0 ┌───────┐
    1 │0 1 0 0│
    2 │1 0 1 1│
    3 │0 0 1 0│
      └───────┘

Rows and columns represent nodes; 1 means connected, 0 means no connection.
Build-Up - 7 Steps
1
FoundationUnderstanding Graph Basics
🤔
Concept: Introduce what a graph is and its components: nodes and edges.
A graph is a collection of points called nodes (or vertices) connected by lines called edges. For example, a social network where people are nodes and friendships are edges. Graphs can be directed (edges have direction) or undirected (edges are two-way).
Result
You know what nodes and edges are and can identify simple graphs.
Understanding nodes and edges is essential because adjacency matrices represent these connections in a structured way.
2
FoundationWhat is an Adjacency Matrix?
🤔
Concept: Explain the adjacency matrix as a square grid representing graph connections.
An adjacency matrix uses a 2D array where rows and columns represent nodes. If node A connects to node B, the cell at row A and column B is 1; otherwise, it is 0. For undirected graphs, the matrix is symmetric. ```typescript // Example for 3 nodes, undirected edge 0-1 const matrix: number[][] = [ [0, 1, 0], [1, 0, 0], [0, 0, 0] ]; console.log(matrix[0][1]); // 1: edge exists ```
Result
You can visualize and create a simple adjacency matrix for a small graph.
Seeing the graph as a matrix helps quickly check connections without searching through lists.
3
IntermediateImplementing Adjacency Matrix in TypeScript
🤔Before reading on: do you think the matrix should store booleans or numbers? Commit to your answer.
Concept: Show how to create and fill an adjacency matrix using TypeScript arrays.
We create a 2D array of numbers initialized to 0. To add an edge, set the corresponding cell to 1. For example, to connect node 0 to node 1, set matrix[0][1] = 1. For undirected graphs, also set matrix[1][0] = 1. ```typescript class AdjacencyMatrix { private matrix: number[][]; constructor(numNodes: number) { this.matrix = Array(numNodes).fill(0).map(() => Array(numNodes).fill(0)); } addUndirectedEdge(from: number, to: number): void { this.matrix[from][to] = 1; this.matrix[to][from] = 1; } hasEdge(from: number, to: number): boolean { return this.matrix[from][to] === 1; } } const graph = new AdjacencyMatrix(4); graph.addUndirectedEdge(0, 1); console.log(graph.hasEdge(0, 1)); // true ```
Result
A TypeScript adjacency matrix that correctly represents graph edges.
Knowing how to implement the matrix in code bridges theory and practice, making graph algorithms possible.
4
IntermediateHandling Directed and Undirected Graphs
🤔Before reading on: do you think the adjacency matrix for directed graphs is always symmetric? Commit to yes or no.
Concept: Explain the difference in matrix symmetry between directed and undirected graphs.
In undirected graphs, edges go both ways, so matrix[i][j] equals matrix[j][i]. In directed graphs, edges have direction, so matrix[i][j] can be 1 while matrix[j][i] is 0. This affects how we read and update the matrix. ```typescript // Directed graph example class AdjacencyMatrix { private matrix: number[][]; constructor(numNodes: number) { this.matrix = Array(numNodes).fill(0).map(() => Array(numNodes).fill(0)); } addDirectedEdge(from: number, to: number): void { this.matrix[from][to] = 1; } hasEdge(from: number, to: number): boolean { return this.matrix[from][to] === 1; } } const graph = new AdjacencyMatrix(3); graph.addDirectedEdge(0, 1); // Only matrix[0][1] = 1 console.log(graph.hasEdge(0, 1)); // true console.log(graph.hasEdge(1, 0)); // false ``` // In class, add: // addDirectedEdge(from: number, to: number): void { // this.matrix[from][to] = 1; // }
Result
You understand how to represent both graph types using adjacency matrices.
Recognizing matrix symmetry helps avoid bugs and correctly interpret graph directionality.
5
IntermediateWeighted Graphs with Adjacency Matrices
🤔Before reading on: do you think adjacency matrices can store weights instead of just 0 or 1? Commit to yes or no.
Concept: Extend adjacency matrices to store edge weights instead of simple connections.
Instead of 0 or 1, cells store numbers representing edge weights (like distance or cost). A 0 or special value (like Infinity) means no connection. This allows representing more complex graphs. ```typescript class WeightedAdjacencyMatrix { private matrix: number[][]; constructor(numNodes: number) { this.matrix = Array(numNodes).fill(0).map(() => Array(numNodes).fill(Infinity)); for (let i = 0; i < numNodes; i++) { this.matrix[i][i] = 0; } } addEdge(from: number, to: number, weight: number): void { this.matrix[from][to] = weight; } getWeight(from: number, to: number): number { return this.matrix[from][to]; } } const wGraph = new WeightedAdjacencyMatrix(3); wGraph.addEdge(0, 1, 5); console.log(wGraph.getWeight(0, 1)); // 5 ```
Result
You can represent weighted graphs and understand how weights affect the matrix.
Using weights in the matrix enables algorithms like shortest path to work directly with the matrix.
6
AdvancedSpace and Time Complexity of Adjacency Matrices
🤔Before reading on: do you think adjacency matrices are efficient for very large sparse graphs? Commit to yes or no.
Concept: Analyze how adjacency matrices use memory and how fast they allow checking connections.
Adjacency matrices use O(n²) space for n nodes, which can be large for big graphs. Checking if two nodes connect is O(1) time. However, for sparse graphs with few edges, this wastes space compared to adjacency lists. ```typescript function spaceUsage(numNodes: number): number { return numNodes * numNodes * 4; // approx bytes for number } console.log(spaceUsage(1000)); // 4MB ```
Result
You understand when adjacency matrices are practical and when they are not.
Knowing complexity helps choose the right graph representation for your problem.
7
ExpertOptimizations and Real-World Usage
🤔Before reading on: do you think adjacency matrices can be compressed or optimized for large graphs? Commit to yes or no.
Concept: Explore advanced techniques to optimize adjacency matrices and their use in real systems.
Sparse matrices can be stored using compressed formats to save space. GPUs use adjacency matrices for parallel graph processing. Some algorithms exploit matrix multiplication on adjacency matrices for fast computations. ```typescript // Pseudo-code for CSR (Compressed Sparse Row) interface CSR { values: number[]; colIndices: number[]; rowPointers: number[]; } // Implementation would map non-zero entries efficiently ```
Result
You see how adjacency matrices scale and adapt in professional environments.
Understanding these optimizations reveals the power and limits of adjacency matrices beyond simple examples.
Under the Hood
An adjacency matrix is stored as a 2D array in memory, where each cell corresponds to a pair of nodes. Accessing matrix[i][j] directly checks if an edge exists, making lookups very fast. Internally, this array is contiguous memory, allowing efficient CPU caching. For weighted graphs, the values represent edge weights, and special values indicate no edge.
Why designed this way?
The adjacency matrix was designed for simplicity and speed of access. Early computer memory models favored fixed-size arrays for predictable performance. Alternatives like adjacency lists save space but require traversal to check edges. The matrix trades space for constant-time edge queries, which suits dense graphs or algorithms needing quick edge checks.
Graph Nodes: 0,1,2,3

Memory Layout:
┌───────────────┐
│ matrix[0][0]  │
│ matrix[0][1]  │
│ matrix[0][2]  │
│ matrix[0][3]  │
│ matrix[1][0]  │
│ matrix[1][1]  │
│ ...           │
└───────────────┘

Access:
Node i -> row i -> column j -> matrix[i][j] = edge presence or weight
Myth Busters - 4 Common Misconceptions
Quick: Is an adjacency matrix always symmetric? Commit to yes or no.
Common Belief:People often think adjacency matrices are always symmetric because many graphs are undirected.
Tap to reveal reality
Reality:Adjacency matrices are symmetric only for undirected graphs. Directed graphs have asymmetric matrices.
Why it matters:Assuming symmetry can cause incorrect graph traversal or edge checks in directed graphs.
Quick: Does an adjacency matrix always use less memory than adjacency lists? Commit to yes or no.
Common Belief:Some believe adjacency matrices are more memory-efficient because they are simple arrays.
Tap to reveal reality
Reality:Adjacency matrices use O(n²) memory regardless of edges, often more than adjacency lists for sparse graphs.
Why it matters:Using adjacency matrices for large sparse graphs wastes memory and can slow down programs.
Quick: Can adjacency matrices store edge weights? Commit to yes or no.
Common Belief:Many think adjacency matrices only store 0 or 1 for edges.
Tap to reveal reality
Reality:Adjacency matrices can store any numeric weight, not just 0 or 1.
Why it matters:Limiting adjacency matrices to binary values restricts their use in weighted graph algorithms.
Quick: Is checking if an edge exists in an adjacency matrix always slower than adjacency lists? Commit to yes or no.
Common Belief:Some believe adjacency lists are always faster for edge checks.
Tap to reveal reality
Reality:Adjacency matrices provide O(1) edge existence checks, faster than adjacency lists which can be O(k) where k is neighbors count.
Why it matters:Misunderstanding this can lead to choosing inefficient data structures for certain algorithms.
Expert Zone
1
Adjacency matrices can be combined with bitsets to reduce memory and speed up boolean operations on edges.
2
In parallel computing, adjacency matrices allow matrix multiplication techniques to solve graph problems efficiently.
3
Sparse adjacency matrices can be stored in compressed sparse row (CSR) or compressed sparse column (CSC) formats to save space while retaining fast access.
When NOT to use
Avoid adjacency matrices for very large sparse graphs where most entries are zero; use adjacency lists or edge lists instead. For dynamic graphs with frequent node additions/removals, adjacency lists are more flexible.
Production Patterns
Adjacency matrices are used in network routing algorithms where quick edge lookup is critical, in GPU-based graph processing for parallelism, and in dense graph problems like social network analysis or image segmentation.
Connections
Adjacency List Representation
Alternative graph representation with different space-time tradeoffs.
Understanding adjacency matrices clarifies why adjacency lists save space for sparse graphs but have slower edge checks.
Matrix Multiplication
Adjacency matrices enable graph algorithms through matrix operations.
Knowing adjacency matrices lets you apply linear algebra techniques to solve graph problems like path counting.
Social Network Analysis
Graphs model social connections; adjacency matrices represent these networks.
Seeing social networks as adjacency matrices helps analyze relationships and influence patterns mathematically.
Common Pitfalls
#1Using adjacency matrix for a large sparse graph wastes memory.
Wrong approach:const matrix = Array(10000).fill(0).map(() => Array(10000).fill(0)); // huge 10000x10000 matrix
Correct approach:Use adjacency list: const graph = Array(10000).fill(null).map(() => []); // stores only edges
Root cause:Not understanding the space complexity of adjacency matrices leads to inefficient memory use.
#2Assuming adjacency matrix is symmetric for directed graphs.
Wrong approach:matrix[i][j] = 1; matrix[j][i] = 1; // forces symmetry incorrectly
Correct approach:matrix[i][j] = 1; // only set edge direction needed
Root cause:Confusing undirected and directed graph properties causes incorrect graph representation.
#3Using 0 to represent both no edge and zero-weight edge.
Wrong approach:matrix[i][j] = 0; // means no edge and zero weight indistinguishable
Correct approach:Use Infinity or null for no edge, 0 for zero weight: matrix[i][j] = Infinity; // no edge
Root cause:Not distinguishing between absence of edge and zero weight leads to algorithm errors.
Key Takeaways
An adjacency matrix is a simple 2D grid that shows connections between graph nodes with fast lookup.
It uses more memory for large graphs, especially if many nodes have few connections.
Adjacency matrices can represent both directed and undirected graphs, with symmetry indicating undirected edges.
They can store weights, enabling complex graph algorithms beyond simple connectivity.
Choosing adjacency matrices or other representations depends on graph size, density, and algorithm needs.

Practice

(1/5)
1. What does an adjacency matrix represent in a graph?
Adjacency matrix is a way to show connections between nodes. What does a 1 in the matrix mean?
easy
A. There is no edge between two nodes
B. The graph is weighted
C. The nodes are the same
D. There is a direct edge between two nodes

Solution

  1. Step 1: Understand adjacency matrix basics

    An adjacency matrix uses rows and columns to represent nodes. Each cell shows if two nodes connect.
  2. Step 2: Interpret the value 1 in the matrix

    A value of 1 means there is a direct edge between the nodes represented by that row and column.
  3. Final Answer:

    There is a direct edge between two nodes -> Option D
  4. Quick Check:

    1 means edge exists [OK]
Hint: 1 means connected, 0 means no connection [OK]
Common Mistakes:
  • Thinking 1 means no edge
  • Confusing node identity with connection
  • Assuming matrix shows weights always
2. Which of the following is the correct TypeScript syntax to declare a 3x3 adjacency matrix initialized with zeros without shared row references?
easy
A. const matrix: number[][] = [[0,0,0],[0,0,0],[0,0,0]];
B. const matrix: number[3][3] = new Array(3).fill(new Array(3).fill(0));
C. const matrix = Array(3).map(Array(3).fill(0));
D. const matrix: number[][] = new Array(3).fill(new Array(3).fill(0));

Solution

  1. Step 1: Check TypeScript array declaration syntax

    const matrix: number[][] = [[0,0,0],[0,0,0],[0,0,0]]; uses explicit 2D array with nested arrays and zeros, which is valid syntax and creates independent rows.
  2. Step 2: Identify issues in other options

    const matrix: number[3][3] = new Array(3).fill(new Array(3).fill(0)); uses invalid TypeScript syntax for fixed-size arrays. const matrix = Array(3).map(Array(3).fill(0)); passes an array to map() instead of a function, causing a runtime error. const matrix: number[][] = new Array(3).fill(new Array(3).fill(0)); uses fill with the same inner array reference, causing shared rows.
  3. Final Answer:

    const matrix: number[][] = [[0,0,0],[0,0,0],[0,0,0]]; -> Option A
  4. Quick Check:

    Explicit nested arrays with zeros [OK]
Hint: Use explicit nested arrays to avoid shared references [OK]
Common Mistakes:
  • Using fill with same inner array causing shared rows
  • Passing non-function to map()
  • Wrong type annotations
3. Given the following adjacency matrix for a directed graph:
const matrix = [
  [0, 1, 0],
  [0, 0, 1],
  [1, 0, 0]
];
console.log(matrix[2][0]);

What will be the output?
medium
A. 1
B. Error
C. undefined
D. 0

Solution

  1. Step 1: Locate matrix[2][0]

    Row 2 is [1, 0, 0], so element at index 0 is 1.
  2. Step 2: Confirm output of console.log

    console.log prints the value 1 found at matrix[2][0].
  3. Final Answer:

    1 -> Option A
  4. Quick Check:

    matrix[2][0] = 1 [OK]
Hint: Remember matrix[row][column] indexing [OK]
Common Mistakes:
  • Confusing row and column indices
  • Expecting zero instead of one
  • Thinking index out of range
4. Consider this TypeScript code snippet to create an adjacency matrix for 3 nodes:
const size = 3;
const matrix = new Array(size).fill(new Array(size).fill(0));
matrix[0][1] = 1;
console.log(matrix);

What is the problem with this code?
medium
A. It creates a matrix with all zeros correctly
B. The matrix is not initialized at all
C. All rows point to the same inner array, so all rows change when one changes
D. It throws a runtime error

Solution

  1. Step 1: Understand fill with reference types

    Using fill with new Array(size).fill(0) creates one inner array shared by all rows.
  2. Step 2: Effect of modifying matrix[0][1]

    Changing matrix[0][1] changes the shared inner array, so all rows show the change.
  3. Final Answer:

    All rows point to the same inner array, so all rows change when one changes -> Option C
  4. Quick Check:

    Shared inner array causes unexpected updates [OK]
Hint: Avoid fill with objects/arrays; use map for unique rows [OK]
Common Mistakes:
  • Assuming fill creates independent arrays
  • Ignoring shared reference behavior
  • Expecting only one row to change
5. You have an undirected graph with 4 nodes. You want to represent it using an adjacency matrix in TypeScript. Which of the following code snippets correctly initializes the matrix and sets an edge between node 1 and node 3?
hard
A. const size = 4; const matrix = new Array(size).fill(new Array(size).fill(0)); matrix[1][3] = 1; matrix[3][1] = 1;
B. const size = 4; const matrix = Array.from({ length: size }, () => Array(size).fill(0)); matrix[1][3] = 1; matrix[3][1] = 1;
C. const size = 4; const matrix = Array(size).fill(Array(size).fill(0)); matrix[1][3] = 1;
D. const size = 4; const matrix = Array(size).map(() => Array(size).fill(0)); matrix[1][3] = 1;

Solution

  1. Step 1: Check matrix initialization for unique rows

    const size = 4; const matrix = Array.from({ length: size }, () => Array(size).fill(0)); matrix[1][3] = 1; matrix[3][1] = 1; uses Array.from with a function to create unique inner arrays, avoiding shared references.
  2. Step 2: Verify setting edges for undirected graph

    Setting matrix[1][3] and matrix[3][1] to 1 correctly represents an undirected edge.
  3. Step 3: Identify issues in other options

    Options B and C use fill causing shared inner arrays. const size = 4; const matrix = Array(size).map(() => Array(size).fill(0)); matrix[1][3] = 1; initializes correctly but only sets matrix[1][3] = 1, missing matrix[3][1] = 1 for undirected graph.
  4. Final Answer:

    const size = 4; const matrix = Array.from({ length: size }, () => Array(size).fill(0)); matrix[1][3] = 1; matrix[3][1] = 1; -> Option B
  5. Quick Check:

    Use Array.from with function for unique rows [OK]
Hint: Use Array.from with function to avoid shared rows [OK]
Common Mistakes:
  • Using fill causing shared inner arrays
  • Using map on empty array without initialization
  • Setting only one direction for undirected edge
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard