Data Structures & Algorithms
Core concepts, Big-O complexity analysis, and fundamental problem-solving techniques for software engineers.
Brute Force Technique
Brute force technique is a strategy in which we try all the possible solutions to get the correct answer.
It is a straightforward approach that tries all possible solutions or uses the most basic logic to solve a problem
Example: If you want to find the factor of a number, then in the brute force technique you will check all the numbers from 1 till that number to see if they are part of that number or not.
var n = 15;
for (var i = 1; i <= n; i++) {
if (n % i == 0) {
console.log('Factor is ' + i);
}
}Advantages of Brute Force
| Title | Description |
|---|---|
| Simple to Implement | Easy to write and understand; good for beginners and quick prototyping. |
| Guaranteed to Work | It covers all cases because it doesn't rely on optimization tricks. |
| Good for Small Inputs | If the data size is small, brute force works just fine. |
| Helps Understand the Problem | Brute force often helps you see patterns for optimizing later. |
| No Extra Knowledge Required | Doesn’t require understanding of advanced algorithms or data structures. |
Disadvantages of Brute Force
| Title | Description |
|---|---|
| Inefficient for Large Inputs | Time complexity is often high (e.g., O(n^2), O(2^n)), making it slow. |
| Doesn’t Scale | Not suitable for real-time systems or large datasets. |
| High Memory Usage | May use unnecessary space or re-compute the same things multiple times. |
| Not Suitable for Interviews | Most interviewers expect you to optimize beyond brute-force solutions. |
| Misses Patterns | It might solve the problem but doesn't reveal deeper insights or optimal techniques. |
Time Complexity
Time complexity tells how much time your program will take (in steps or operations) as the input size increases.
let str = 'hello';
for (let i = 0; i < str.length; i++) {
console.log(str[i]);
}- This loop is printing each character once. If there are 5 characters in the string, it will run 5 times.
- It means, If the input is 100, then the loop will run 100 times
- So Time Complexity = O(n)
Space Complexity
Space Complexity tells how much extra memory (RAM) your program is using based on the input.
let str = 'hello'; let rev = ''; // Extra memory = n characters // Space Complexity = O(n)
- We are created a new string (rev) that is as large as the input.
- Therefore: Extra memory = 'n' characters
- So, Space Complexity = O(n)
What is O(n) notation
This notation is called Big-O Notation
It shows how the performance of an algorithm changes as the input size n increases.
| Title | Description | Example |
|---|---|---|
| O(1) | Constant Time (very fast, no matter the input size) | console.log("Hi") |
| O(n) | Linear Time (as the input increases, so does the time) | Loop from 0 to n |
| O(n²) | Quadratic Time (time increases rapidly as the input size increases) (Quadratic Time (input size बढ़ने पर समय बहुत तेज़ बढ़ता है)) | Nested loops |
| O(log n) | Logarithmic Time (very fast algorithm) (Logarithmic Time (बहुत तेज़ algorithm)) | Binary Search |
| O(n log n) | Efficient Sorting Algorithms | Merge Sort, Quick Sort |
Examples
Example 1: O(1) – Constant Time
function printFirstElement(arr) {
console.log(arr[0]);
}Example 2: O(n) – Linear Time
function printAllElements(arr) {
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
}Example 3: O(n^2) – Quadratic Time
function printPairs(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
console.log(arr[i], arr[j]);
}
}
}Two Pointer Technique
Two-pointer is a common DSA pattern where two indices move towards each other to solve array or string problems efficiently.
- Convert string to array (if allowed).
- Use 2 pointers — one at start, one at end.
- Swap while left < right.
let str = 'hello';
let arr = str.split('');
let left = 0, right = arr.length - 1;
while (left < right) {
[arr[left], arr[right]] = [arr[right], arr[left]];
left++;
right--;
}
console.log(arr.join(''));Sliding Window Technique
The Sliding Window technique is a powerful DSA pattern used when you need to analyze a subset (window) of elements in a contiguous array or string.
It uses two pointers that move in the same direction (mostly left → right) to expand and shrink a window dynamically.
This helps reduce time complexity compared to using nested loops.
- Define the window size or condition (for example, subarray length = K).
- Iterate through the array while adding the current element to the window.
- When the window reaches the required size, calculate or compare the result (like sum or max).
- Before sliding forward, remove the element that’s leaving the window from the sum/count.
- Continue sliding the window until the end of the array is reached.
const arr = [2, 1, 5, 1, 3, 2];
const k = 3;
let maxSum = 0, windowSum = 0;
for (let i = 0; i < arr.length; i++) {
windowSum += arr[i]; // add current element
if (i >= k - 1) {
maxSum = Math.max(maxSum, windowSum);
windowSum -= arr[i - (k - 1)]; // remove left element
}
}
console.log(maxSum); // 9 (5 + 1 + 3)