Code Like a Girl
Arrays: From Classroom Attendance to Algorithms
Think about a classroom during attendance.
Each student is assigned a roll number:
- Roll No 1 → Rahul
- Roll No 2 → Priya
- Roll No 3 → Arjun
- Roll No 4 → Sneha
Now suppose the teacher wants to know:
“Who is Roll No 25?”
The teacher doesn’t need to read every student’s name before that. Since each student already has a position, they can directly look up Roll №25.
Arrays work similarly. Every element has a position (index), allowing quick access. That ability to access information by its position is one of the reasons arrays are so useful.
What’s interesting is that most developers start using arrays long before they formally learn Data Structures and Algorithms. Whenever you’ve worked with a list of users, products, notifications, messages, comments, or transactions, you’ve likely been using arrays without giving them much thought.
Arrays are everywhere because a large number of real-world applications deal with collections of similar pieces of data. Whether you’re displaying products on an e-commerce website, showing notifications in a mobile app, or rendering search results on Google, chances are an array is involved somewhere behind the scenes.
Understanding arrays is important because they are not just another data structure. They are the foundation on which many other DSA concepts and problem-solving patterns are built.
So What Exactly Is an Array?An array is a data structure that stores multiple values under a single variable name.
Imagine having to store the names of students in a classroom without arrays:
const roll_No1 = "John";
const roll_No2 = "Sarah";
const roll_No3 = "Mike";
const roll_No4 = "Emma";
This works when there are only a few users, but it quickly becomes difficult to manage as the list grows.
Arrays solve this problem by allowing us to group related values together:
const students = ["John", "Sarah", "Mike", "Emma"];
Instead of managing four separate variables, we now have a single array that contains all the users.
Each value inside the array is assigned a position known as an index. One thing that need to remember is that array indexing starts from 0, not 1.
const students = ["John", "Sarah", "Mike", "Emma"];
console.log(students[0]); // John
console.log(students[1]); // Sarah
console.log(students[2]); // Mike
Here, "John" is stored at index 0, "Sarah" at index 1, and "Mike" at index 2.
This idea of assigning a position to every element is what makes arrays so powerful.
Why Are Arrays So Fast?Let’s go back to our classroom example.
Suppose a teacher wants to know who has Roll No 50. The teacher doesn’t need to start from Roll No 1 and count all the way to 50. Since every student already has an assigned position, they can directly look up Roll No 50.
Arrays work in much the same way.
Because every element has an index, the computer can directly access the required position instead of searching through the entire collection.
const numbers = [10, 20, 30, 40, 50];
console.log(numbers[3]);
When we ask for numbers[3], the computer doesn't start from the beginning and count its way to the fourth element. It already knows exactly where that position is located and can retrieve it immediately.
Whether the array contains 5 elements or 5 million elements, accessing an element by its index requires essentially the same amount of work.
That’s why array access is considered O(1), also known as constant time complexity. The size of the array doesn’t affect how quickly the element can be retrieved.
Common Array Operations and Their ComplexityNow that we understand how arrays are organized, let’s connect them to the complexity concepts we discussed in Episode 1.
Some array operations are extremely fast, while others become more expensive as the array grows.
♦Understanding why these complexities differ is much more valuable than simply memorizing them.
Accessing an ElementSuppose we want to access the element at index 5:
arr[5]
Since every element in an array has a fixed position, the computer can directly jump to that location and retrieve the value.
There is no need to check the elements before it or search through the array.
That’s why accessing an element by index takes O(1) time.
Searching for an ElementNow consider a different problem. Instead of asking for a specific position, we’re looking for a specific value.
const arr = [10, 20, 30, 40, 50];
Suppose we want to find the value 50.
The computer has no way of knowing where that value is located, so it starts checking the elements one by one.
Is it 10?
Is it 20?
Is it 30?
Is it 40?
Is it 50?
In the worst case, the value might be at the very end of the array, or it might not exist at all. That means every element may need to be inspected.
As the array grows, the amount of work grows as well, which gives us a time complexity of O(n).
Inserting at the EndAdding a new element to the end of an array is usually straightforward.
[10, 20, 30, 40]
Insert 50:
[10, 20, 30, 40, 50]
Nothing else needs to move, so this operation typically takes O(1) time.
Inserting at the BeginningNow let’s insert a value at the start of the array.
[10, 20, 30, 40]
Insert 5:
[5, 10, 20, 30, 40]
From our perspective, this looks like a simple operation. Internally, however, every existing element must shift one position to the right to make space for the new value.
10 → moves to index 1
20 → moves to index 2
30 → moves to index 3
40 → moves to index 4
The larger the array becomes, the more elements need to be moved.
That’s why inserting at the beginning has a time complexity of O(n).
Deleting from the BeginningA similar situation occurs when we remove the first element.
[10, 20, 30, 40]
Remove 10:
[20, 30, 40]
After the deletion, every remaining element must shift one position to the left to fill the gap.
Because the amount of work grows with the size of the array, deleting from the beginning also takes O(n) time.
The key takeaway is that arrays are incredibly efficient when you know exactly where the data is located, but operations that require shifting many elements can become expensive as the array grows.
Problem 1: Find the Largest Number in an ArrayLet’s start with one of the most common array problems.
Given an array of numbers, find the largest value present in it.
Input:
[5, 9, 2, 15, 7]
Output:
15How Should We Think About It?
Imagine all the numbers are placed on a table.
Instead of comparing every number with other numbers, we can keep track of the largest number we’ve seen so far.
We start by assuming the first number is the largest. Then, as we move through the array, we compare each number against our current largest value. Whenever we find a bigger number, we update it.
By the time we reach the end of the array, the value we’re holding will be the largest number in the entire array.
Solutionfunction findLargest(arr) {
let largest = arr[0];
for (let num of arr) {
if (num > largest) {
largest = num;
}
}
return largest;
}Array = [5, 9, 2, 15, 7]
Start:
largest = 5
5 > 5 ? No
largest = 5
9 > 5 ? Yes
largest = 9
2 > 9 ? No
largest = 9
15 > 9 ? Yes
largest = 15
7 > 15 ? No
largest = 15
Answer = 15Complexity Analysis
We traverse the array exactly once, checking each element against the current largest value.
- Time Complexity: O(n)
- Space Complexity: O(1)
The time complexity is O(n) because every element is visited once. The space complexity is O(1) because we only use a single variable, largest, regardless of how large the array becomes.Pattern Behind This Problem
This problem introduces one of the most fundamental patterns in Data Structures and Algorithms: Linear Traversal.
In this problem, we start at the beginning of the array and examine every number exactly once while keeping track of the largest value we’ve seen so far. While traversing, we can perform whatever operation the problem requires, such as finding a maximum value, counting elements, calculating a sum, or checking a condition. Although the pattern seems simple, it appears surprisingly often. You’ll encounter it while working with arrays, strings, linked lists, trees, and many other data structures.
As we move through this series, we’ll build on this foundation and explore more advanced patterns that evolve from the same basic idea.
Problem 2: Count Even Numbers in an ArrayConsider the following array:
[2, 5, 8, 11, 14, 19]
We need to count how many even numbers are present in the array.
The answer is:
3
because 2, 8, and 14 are even.
Before writing any code, think about what information we actually need. The problem is asking for the count of even numbers, not the numbers themselves. That means there is no need to store even numbers we find.
Instead, we can start with a counter set to 0 and traverse the array one element at a time. Whenever we encounter an even number, we increment the counter by one. By the time we reach the end of the array, the counter will tell us exactly how many even numbers are present.
Instead of storing every even number, we only need a count.
Start with zero.
Whenever you encounter an even number, increase the count.
Continue until the array ends.
Solutionfunction countEvenNumbers(arr) {
let count = 0;
for (let num of arr) {
if (num % 2 === 0) {
count++;
}
}
return count;
}Complexity AnalysisAgain, every element is visited once.
Time Complexity: O(n)
Space Complexity: O(1)
Pattern Behind This ProblemBehind this solution is the same Linear Traversal pattern that we saw in the previous problem. We move through the array one element at a time and perform a small piece of work for each element.
However, this problem introduces another important concept: maintaining a running value.
Instead of storing every even number we encounter, we keep track of only the information we actually need. In this case, that information is the count of even numbers, so we continuously update a single variable as we traverse the array.
This idea shows up frequently in DSA. Whether you’re calculating a running sum, tracking a maximum value, counting occurrences, or maintaining a window of information, the underlying approach is process each element and keep updating a variable that represents the current state of the solution.
The Bigger PictureAt first glance, arrays might look simple.
In fact, many developers underestimate them because they are usually the first data structure we learn.
But arrays are the foundation for a huge portion of Data Structures and Algorithms.
Many popular patterns begin with arrays:
- Linear Traversal
- Two Pointers
- Sliding Window
- Prefix Sum
- Binary Search
- Hashing
- Kadane’s Algorithm
The important thing is to recognize that arrays are where these patterns start.
Once you’re comfortable traversing arrays and understanding their complexity, learning those patterns becomes much easier.
For anyone interested in practicing further, here are a few LeetCode problems that align well with the concepts covered in this episode.
1480. Running Sum of 1D Array
1732. Find the Highest Altitude
2011. Final Value of Variable After Performing Operations
485. Max Consecutive Ones
414. Third Maximum Number
A Little More Challenging
724. Find Pivot Index
121. Best Time to Buy and Sell Stock
53. Maximum Subarray
697. Degree of an Array
1748. Sum of Unique Elements
In the next episode, we’ll explore the Two Pointers pattern and discover why having two positions moving through an array can often be more useful than having just one.
♦Arrays: From Classroom Attendance to Algorithms was originally published in Code Like A Girl on Medium, where people are continuing the conversation by highlighting and responding to this story.