An open API service indexing awesome lists of open source software.

https://github.com/chanda-abdul/dsa-big-o

A repository for my Data Structures & Algorithms Big O Notation drills
https://github.com/chanda-abdul/dsa-big-o

Last synced: 8 months ago
JSON representation

A repository for my Data Structures & Algorithms Big O Notation drills

Awesome Lists containing this project

README

          

# Big O classifications

![](https://he-s3.s3.amazonaws.com/media/uploads/ece920b.png)

|Big-O Notation| n = 10| n = 100| n = 1000|
|---|---|---|---|
|O(1)|1|1|1|
|O(log n)|3|6|9|
|O(n)|10|100|1000|
|O(n^2)|100|10000|1000000|
|O(2^n)|1024|2^100|2^1000|

## Constant time O(1)
- Constant time complexity is the "holy grail".
- No matter the size of your input, the algorithm will take the same amount of time to complete.
- Examples of O(1) algorithms are accessing an array item or performing basic arithmetic operations (e.g., adding 2 numbers). The following is an example of an algorithm with O(1) runtime complexity.

````
function getRandomItem(array) {
let ticks = 0;
// Get a random number and access that element in the array
const item = array[Math.floor(Math.random() * array.length)];
ticks++;
return {
result: item,
ticks: ticks
};
}
````

## Logarithmic time O(log(n))
- Logarithmic time complexity `(O(log n))` is the next best thing after constant time.
- While logarithmic time complexity algorithms do take longer with larger inputs, running time increases slowly.
- It is also characteristic of logarithmic algorithms that they cut the problem size in half each round through.

````
function howManyLessThanNitems(arr, n) {
let ticks = 0;
/* If the 1st element in the array is greater than `n`, return 0,
because no items in the array are less than `n`. */
if (!arr.length || arr[0] >= n) {
ticks++;
return 0;
}

let lowIndex = 0, highIndex = arr.length;

while (highIndex > lowIndex) {
// Find midpoint
let midIndex = Math.floor((highIndex + lowIndex) / 2);
/* If `midIndex` element is greater than `n`, that means all elements
to the right of `midIndex` are also greater than `n`, so
we only need to focus on elements to the left of `midIndex`.
We set `highIndex` to the current value of `midIndex` so next time
through the loop, we'll only look at the left half */
if (arr[midIndex] >= n) {
highIndex = midIndex;
ticks++;
}

/* If the element to the right of `midIndex` is less than `n`, then we
know that we need to check the items to the right of `midIndex`, so
we set `lowIndex` to the current value of `midIndex`, so that next
time through the loop we only look at the right side */
else if (arr[midIndex + 1] < n) {
lowIndex = midIndex;
ticks++;
}

/* Otherwise, if the element to the right of `midIndex` is greater
than or equal to `n`, we know that the item at `midIndex` is the last
item that's less than `n`, so we return `midIndex + 1` to get the total
number of items that are less than `n` */
else {
ticks++;
return {
result: midIndex + 1,
ticks: ticks
}
}
}
}

howManyLessThanNitems([1,2,3], 2);
howManyLessThanNitems([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100], 99 );
````

## Linear time O(n)
- Algorithms with linear time complexity `(O(n))` have running times that are directly proportional to the size `(n)` of the input. Given input `a` and input `b`, where `b` is twice as large as `a`, it will take a linear algorithm 2 times as long to process `b` compared to `a`.
- Some examples of linear complexity algorithms are summing the elements in an array and finding the minimum or maximum value in an array.

````
function findMin(array){
let min = array[0], ticks = 1;
for (let i = 1; i < array.length; i++) {
ticks++;
if (array[i] < min) {
min = array[i];
}
}
return {
result: min,
ticks: ticks
};
}

findMin([1,2,3]);
findMin([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
findMin([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]);
````

## Polynomial time O(n^k)
- An algorithm with polynomial time complexity has a running time that would be some input size `n` raised to some constant power `k`.
- The easiest way to understand polynomial time complexity is with nested loops. An algorithm that requires 2 levels of looping over an input would be `O(n^2)` while one requiring 3 levels of looping would be `O(n^3)`. In both cases, we have polynomial time complexity.
````
function hasDuplicates(array) {
let ticks = 0, result = false;
for (let i = 0; i < array.length; i++) {
ticks++;
for (let j = 0; j < array.length; j++) {
ticks++;
if (array[i] === array[j] && i !== j) {
result = true;
}
}
}
return {
result: result,
ticks: ticks
};
}

hasDuplicates([1, 2, 2]);
hasDuplicates([1, 2, 3, 4, 5, 6, 7, 8, 9, 9]);
hasDuplicates([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 99]);
````
## Exponential time O(2^n)
- Algorithms with exponential time complexity `(O(2^n))` have running times that grow rapidly with any increase in input size. For an input of size 2, an exponential time algorithm will take 2^2 = 4 time. With an input of size 10, the same algorithm will take 2^10 = 1024 time, and with an input of size 100, it will take 2^100 = 1.26765060022823 * 1030 time. Yikes!

````
function countTriangle(layers) {
let ticks = 1;
let count = 0; // the number of dots we've counted so far
let layer = 0; // the current layer we're on
let lastLayer = 1; // the number of dots we counted in the previous layer
while (layer < layers) {
ticks++;
let newLayer = 0; // the number of dots we've counted so far in the current layer
for (let i = 0; i < lastLayer; i++) {
ticks++;
newLayer += 2;
}
lastLayer = newLayer;
count += lastLayer;
layer++;
}
return {
result: count,
ticks: ticks
};
}

countTriangle(2);
countTriangle(4);
countTriangle(16);
````

# Data Structures & Alogorithms -Big-O Notation Drills

In these drills, you'll practice determining the big O complexity of algorithms. For each drill, we'll provide a code snippet with a function, and you'll work out the big O complexity by analyzing the code without running it.

## 1. What is the Big O for this?
1) Determine the Big O for the following algorithm: You are sitting in a room with 15 people. You want to find a playmate for your dog, preferably of the same breed. So you want to know if anyone out of the 15 people have the same breed as your dog. You stand up and yell out, who here has a golden retriever and would like to be a playdate for my golden. Someone yells - "I do, be happy to bring him over"

2) Determine the Big O for the following algorithm: You are sitting in a room with 15 people. You want to find a playmate for your dog who is of the same breed. So you want to know if anyone out of the 15 people have the same breed as your dog. You start with the first person and ask him if he has a golden retriever. He says no, then you ask the next person, and the next, and the next until you find someone who has a golden or there is no one else to ask.

## 2. Even or odd
What is the Big O of the following algorithm? Explain your answer

```
function isEven(value) {
if (value % 2 === 0) {
return true;
}
else
return false;
}
}
```

## 3. Are you here?
What is the Big O of the following algorithm? Explain your answer

```function areYouHere(arr1, arr2) {
for (let i = 0; i < arr1.length; i++) {
const el1 = arr1[i];
for (let j = 0; j < arr2.length; j++) {
const el2 = arr2[j];
if (el1 === el2) return true;
}
}
return false;
}
```

## 4. Doubler
What is the Big O of the following algorithm? Explain your answer

```
function doubleArrayValues(array) {
for (let i = 0; i < array.length; i++) {
array[i] *= 2;
}
return array;
}
```

## 5. Naive search
What is the Big O of the following algorithm? Explain your answer

```
function naiveSearch(array, item) {
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
return i;
}
}
}
```

## 6. Creating pairs:
What is the Big O of the following algorithm? Explain your answer

```
function createPairs(arr) {
for (let i = 0; i < arr.length; i++) {
for(let j = i + 1; j < arr.length; j++) {
console.log(arr[i] + ", " + arr[j] );
}
}
}
```

## 7. Compute the sequence
What does the following algorithm do? What is its runtime complexity? Explain your answer

```
function compute(num) {
let result = [];
for (let i = 1; i <= num; i++) {

if (i === 1) {
result.push(0);
}
else if (i === 2) {
result.push(1);
}
else {
result.push(result[i - 2] + result[i - 3]);
}
}
return result;
}
```

## 8. An efficient search
In this example, we return to the problem of searching using a more sophisticated approach than in naive search, above. Assume that the input array is always sorted. What is the Big O of the following algorithm? Explain your answer

```
function efficientSearch(array, item) {
let minIndex = 0;
let maxIndex = array.length - 1;
let currentIndex;
let currentElement;

while (minIndex <= maxIndex) {
currentIndex = Math.floor((minIndex + maxIndex) / 2);
currentElement = array[currentIndex];

if (currentElement < item) {
minIndex = currentIndex + 1;
}
else if (currentElement > item) {
maxIndex = currentIndex - 1;
}
else {
return currentIndex;
}
}
return -1;
}
```

## 9. Random element
What is the Big O of the following algorithm? Explain your answer

```
function findRandomElement(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
```

## 10. What Am I?
What does the following algorithm do? What is the Big O of the following algorithm? Explain your answer

```function isWhat(n) {
if (n < 2 || n % 1 !== 0) {
return false;
}
for (let i = 2; i < n; ++i) {
if (n % i === 0) return false;
}
return true;
}
```
## 11. Tower of Hanoi
The Tower of Hanoi is a very famous mathematical puzzle (some call it game!). This is how it goes:

There are three rods and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks neatly stacked in ascending order of size on one rod, the smallest disk at the top (making a conical shape). The other two rods are empty to begin with.
The goal of the puzzle is to move the entire stack of rods to another rod (can't be the original rod where it was stacked before) where it will be stacked in the ascending order as well. This should be done obeying the following rules: i) Only one disk may be moved at a time ii) Each move consists of taking the upper disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod. iii) A larger disk may not placed on top of a smaller disk
Input:

````
Rod A Rod B Rod C
----
---------
-------------
Output:

Rod A Rod B Rod C
----
---------
-------------
````
Derive an algorithm to solve the Tower of Hanoi puzzle.
Implement your algorithm using recursion. Your program should display each movement of the disk from one rod to another.
If you are given 5 disks, how do the rods look like after 7 recursive calls?
How many moves are needed to complete the puzzle with 3 disks? with 4 disks? with 5 disks?
What is the runtime of your algorithm?
## 12. Iterative version
Solve the drills 1 - 7 from your previous checkpoint (Recursion) iteratively.

## 13. Recursive Big O
Take your solutions from the recursive exercises that you completed in the previous checkpoint and identify the time complexities (big O) of each of them.

## 14. Iterative Big O
Take your solutions from the iterative exercises today and identify the time complexities (big O) of each of them.