Hoi hoi!
Iβm @nyaomaru, a frontend engineer who dislikes crowded places, so I'm planning to take a quiet vacation in September. ποΈ
Have you used DSA View View already? ππ
DSA View View allows you to understand DSA by visualizing how your implementation actually runs.
But just introducing the tool is not enough.
Can it actually help us understand DSA?
In this article, we'll walk through three classic problems:
- Two Sum
- Binary Search
- Bubble Sort
We'll first understand the algorithm, and then see what is actually happening with DSA View View.
Let's learn together! πΈ
πΊοΈ Two Sum
Let's start with a very famous problem.
Given an array of numbers and a target value, find the indices of two numbers whose sum equals the target.
For example,
nums = [2, 7, 11, 15];
target = 9;
The answer is
[0, 1];
Because
2 + 7 = 9
Simple!
So, how should we find them? π€
Brute Force
The easiest approach is probably checking every possible pair.
function twoSum(nums: number[], target: number): number[] {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
return [];
}
This works.
But if the array becomes large, we may need to compare a lot of pairs, right?
The time complexity is O(nΒ²)
Can we avoid checking the same values again and again?
Yes.
Let's use a Map.
function twoSum(nums: number[], target: number): number[] {
const seen = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
const current = nums[i];
const need = target - current;
if (seen.has(need)) {
return [seen.get(need)!, i];
}
seen.set(current, i);
}
return [];
}
The important part is this π
const need = target - current;
Instead of asking
Which two numbers should I combine?
we ask
What number do I need to complete the target?
Let's follow the example.
At first
current = 2
target = 9
need = 9 - 2
= 7
Have we already seen 7?
No.
So we remember 2.
seen = {
2 β 0
}
Next
current = 7
target = 9
need = 9 - 7
= 2
Have we already seen 2?
Yes! ππ
seen = {
2 β 0
}
So
return [0, 1];
Done!
Because we only need to walk through the array once, the time complexity becomes.
Time: O(n)
Space: O(n)
π Let's View View It
The implementation is quite small.
But when I was first learning this pattern, this part still felt a little magical.
if (seen.has(need))
- Where did
needcome from? - What is inside
seenat this moment? - Why does checking the previous values solve the problem?
This is exactly where visualization helps.
With DSA View View, we can move through the runtime one step at a time and inspect how the values change.
2
β
Need 7
β
Remember 2
β
7
β
Need 2
β
Found 2!
π
Now the Map is not just some mysterious trick.
We can actually follow the idea.
Remember what we have already seen, and check whether the value we need is there.
Nice! πΈ
π Binary Search
Next is Binary Search.
Suppose we have this sorted array
[1, 3, 5, 7, 9, 11, 13]
And we want to find
11
Of course, we could start from 1 and check every number.
1 β 3 β 5 β 7 β 9 β 11
That works.
But Binary Search does something smarter.
Instead of checking from the beginning, it checks the middle.
[1, 3, 5, 7, 9, 11, 13]
β
mid
Our middle value is 7.
We are looking for 11.
11 > 7
Because the array is sorted, we already know something very useful.
Everything on the left side of 7 is also smaller than 11.
So, we don't need that half anymore. π
[1, 3, 5, 7, 9, 11, 13]
βββββββββ
search
Now we check the middle of the remaining range.
[9, 11, 13]
β
mid
And
11 === 11
Found it! π
Here is the implementation.
function binarySearch(nums: number[], target: number): number {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (nums[mid] === target) {
return mid;
}
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
There are three important variables.
left
right
mid
They represent the current search range.
For our example, they start like this
left = 0
right = 6
mid = 3
[1, 3, 5, 7, 9, 11, 13]
β β β
left mid right
Because
nums[mid] < target;
we move left.
left = mid + 1;
Now
[1, 3, 5, 7, 9, 11, 13]
β β β
left mid right
And 11 is found.
Why Is Binary Search Fast?
This is the interesting part.
Each step removes about half of the remaining candidates.
If there are 1,000 values, we don't necessarily need 1,000 checks.
It becomes roughly
1000
β
500
β
250
β
125
β
...
That's why Binary Search has
Time: O(log n)
Space: O(1)
But there is one very important condition.
The data must be sorted.
Without sorted data, we cannot safely throw away half of the search range.
π Let's View View It
Binary Search is one of the algorithms that made me want a visualization tool in the first place.
The code itself is short
left = mid + 1;
or
right = mid - 1;
Easy.
But when learning it, I sometimes found myself thinking:
Wait... which part are we searching now? πΏ
When we visualize left, mid, and right, the idea becomes much easier to follow.
We are not randomly changing three numbers.
We are continuously shrinking the search area.
βββββββββββββββ
β
βββββββ
β
βββ
β
β
That's Binary Search!
Cut the unnecessary half.
Then cut it again. And again. And again.
Until we find the answer. βοΈπΈ
π«§ Bubble Sort
Finally, let's sort something!
Consider this array.
[5, 1, 4, 2, 8];
We want.
[1, 2, 4, 5, 8];
Bubble Sort repeatedly compares two neighboring values.
If they are in the wrong order, it swaps them.
Let's look at the beginning.
[5, 1, 4, 2, 8]
β β
Compare
5 > 1
So swap them.
[1, 5, 4, 2, 8]
Next
[1, 5, 4, 2, 8]
β β
Again
5 > 4
Swap!
[1, 4, 5, 2, 8]
And continue.
[1, 4, 5, 2, 8]
β β
5 > 2
Swap!
[1, 4, 2, 5, 8]
Eventually, larger values move toward the end of the array.
They kind of...
bubble up. π«§
That's why it is called Bubble Sort.
Here is a simple implementation:
function bubbleSort(nums: number[]): number[] {
for (let i = 0; i < nums.length - 1; i++) {
for (let j = 0; j < nums.length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
[nums[j], nums[j + 1]] = [nums[j + 1], nums[j]];
}
}
}
return nums;
}
We repeatedly compare
nums[j];
And
nums[j + 1];
and swap them when necessary.
After one full pass, the largest remaining value reaches its correct position near the end.
So on the next pass, we don't need to check that position again.
That's why the inner loop contains.
nums.length - i - 1;
Complexity
Bubble Sort isn't very fast for large arrays.
Its time complexity is
Time: O(nΒ²)
Space: O(1)
So I probably won't suddenly replace production sorting with Bubble Sort tomorrow. πΈ
But as a learning example, I really like it.
Why?
Because you can see the algorithm working.
π Let's View View It
This is probably the most visually satisfying one of the three.
Instead of only reading
[nums[j], nums[j + 1]] = [nums[j + 1], nums[j]];
we can follow the values moving through the array.
[5, 1, 4, 2, 8]
β swap
[1, 5, 4, 2, 8]
β swap
[1, 4, 5, 2, 8]
β swap
[1, 4, 2, 5, 8]
Then another pass begins.
The code contains nested loops, indexes, comparisons, and swaps.
But visually, the basic rule is extremely simple:
Compare neighbors. If the left one is bigger, swap them.
Repeat. Repeat. Repeat.
Sorted! π
π§ What Did We Actually Learn?
These three problems look quite different.
But each one introduces a useful way of thinking.
Two Sum
Remember information from previous steps.
Have I already seen what I need?
Binary Search
Use what we already know to remove impossible candidates.
Can I safely discard half of the search space?
Bubble Sort
Break a larger problem into many small comparisons.
Are these two values in the correct order?
This is one of the things I find interesting about learning DSA.
At first, the implementation can look like a collection of indexes, loops, conditions, and mysterious variables.
But behind the code, there is usually a much simpler idea.
And sometimes I don't fully understand that idea just by staring at the code.
I want to view it. ππ
π― Conclusion
In this article, we looked at three classic algorithms:
- Two Sum with a
Map - Binary Search
- Bubble Sort
And more importantly, we looked at how the data changes while they run.
I think this is where visualization can be especially useful.
- Reading the final implementation tells us what the code is.
- Stepping through it helps us understand why it works.
That's exactly why I built DSA View View.
You can write or load a TypeScript implementation, run it with your own inputs, and move backward and forward through the runtime.
If you are learning DSA too, try taking a problem you already solved and viewing it step by step.
You may notice something you didn't notice when only reading the code. π
And if there is a DSA problem you want me to cover next, please let me know in the comments!
I still have many algorithms to learn myself. πΈ
Let's train our DSA muscles together! πͺ
If you like DSA View View, please give it a star β
nyaomaru
/
dsa-view-view
DSA View View allows you to understand DSA to see the data flow. ππ Of course, it's free.
DSA View View
DSA View View turns TypeScript algorithm functions into step-by-step visual stories. ππ
Write code, run it with structured inputs, and see the arrays, matrices trees, lists, stacks, pointers, and return values move as the function executes.
It is built for those moments when reading the code is not enough and you want to view why the answer changes.
Why Try It?
-
π§ Step through real TypeScript
Paste or edit a function, validate it, then run the exact code in the browser. -
π§© Views that match the data
Arrays become bars, matrices become grids, trees become node graphs, linked lists become chains, and two-pointer area problems get their own visual view. -
π³ DSA-friendly inputs out of the box
TreeNode,ListNode,MinHeap,MaxHeap,PriorityQueue, nested arrays matrices, strings, numbers, and class-style inputs are supported without ceremony. -
π 39 built-in examples
Search by name, browseβ¦
And my DSA View View has launched at TinyLaunch! π Please take a loot π
See you in the next article!







Top comments (0)