Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ Now, let us delve into the code:
def binarySearch (arr, l, r, x):

if r >= l:

mid = l + (r - l)/2

if arr[mid] == x:
return mid
elif arr[mid] > x:
return binarySearch(arr, l, mid-1, x)
return binarySearch(arr, l, mid-1, x)

else:
return binarySearch(arr, mid + 1, r, x)

else:
return -1
```
Expand All @@ -39,6 +38,7 @@ The first time complexity is the best case time complexity. This means that this
```python
if arr[mid] == x:
return mid

```

As you can see, when the middle of the list arr is equal to what you are searching for, it immediately stops recursing. Therefore, if the value you are looking for is exactly in the middle in the first recursion, then you will immediately stop the algorithm.
Expand All @@ -53,10 +53,11 @@ In binary search, the worst case is when the algorithm cannot find what it is lo

```python
elif arr[mid] > x:
return binarySearch(arr, l, mid-1, x)

return binarySearch(arr, l, mid-1, x)
else:
return binarySearch(arr, mid + 1, r, x)
return binarySearch(arr, mid + 1, r, x)

```

As you may notice, you will iterate only half of the list in each iteration, thus making it O(logn). And since the best case scenario is very unlikely to happen, then the average case time complexity shall be the same as the worst case time complexity: O(logn).
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ Identical to BFS, the first step in implementing a DFS algorithm is to construct
from collections import defaultdict

class Graph:

def __init__(self):

self.graph = defaultdict(list)

def addEdge(self, u, v):
Expand Down
Empty file.
5 changes: 0 additions & 5 deletions ...Topic/Module3-Search-and-Sorting-Algos/activities/Act1_SearchingAndSorting/9.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,11 @@ We start our binary search function by setting up a base case.
```python
def binarySearch(arr, l, r, x):
if r >= l:

mid = l + (r - l)/2

if arr[mid] == x:
return mid


elif arr[mid] > x:
return binarySearch(arr, l, mid-1, x)

else:
return binarySearch(arr, mid + 1, r, x)
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
### Merge Sort in Python (Part II)

```python
i = j = k = 0
i = j = k = 0
while i < len(lefthalf) and j < len(righthalf):
if lefthalf[i] <= righthalf[j]:
alist[k]=lefthalf[i]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
### Sorting a Linked List

The goal for this activity is to sort an unsorted linked list by using the **Insertion Sort** algorithm.

![Insertion Sort](https://i.ytimg.com/vi/OGzPmgsI-pQ/maxresdefault.jpg)

As a reminder, insertion sort divides a list into two parts: the sorted part and the unsorted part. The algorithm starts off with the first two elements in the list, and sorts them. This will be the sorted part of the list while the rest is the unsorted part. Then as it traverses the list, it will add another element to the sorted part of the list and resort it. This will continue until the whole list is sorted.

Here are some examples of what our solution will do:

**Example 1:**

```
Input: 4->2->1->3
Output: 1->2->3->4
```

**Example 2:**

```
Input: -1->5->3->4->0
Output: -1->0->3->4->5
```

Note:

- The linked list will only contain integers
- The solution will look similar to the insertion sort algorithm discussed before
- The linked list must be sorted from smallest to greatest as shown by the example

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
To start off, we are given the definition of a singly linked list:

```python
function ListNode(val) {
this.val = val;
this.next = null;
}
```

This function for the linked list is very important as you will see us using it to implement the solution. As a little explanation, the `this.val=val;` part simply makes the current val of the node you are in to be the val given as the argument for our ListNode function. The `this.next=null` simply makes the next val be null.



Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Now that we have our linked list definition, we can start on the actual solution. The first part of the code is :

```python
def insertionSortList(self, head):
p = dummy = ListNode(0)
cur = dummy.next = head
```

In this part of the code, `insertionSortList(self, head)` Is the name of our function that will sort the linked list and solve our problem. It is also here that p is initialized along with dummy to have a val of 0 and be the root of the linked list. In our solution, p's role will be to be the pointer for where cur will insert after. And our dummy variable is the linked list that we will return as a sorted linked list.

In the second line of the code, `cur` and `dummy.next` are initialized to be the head of the linked list. In our solution, `cur` will be used to compare with other elements and ensure that everything is sorted through said comparisons. These pointers are necessary to keep track of where things are as well as to determine if the linked list is sorted and if not, where it is not sorted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Next up is the while loop. It is here that our solution will iterate over each and every element inside the linked list once:

```python
while cur and cur.next:
```

The above basically means that while `cur` and `cur.next` exists, then the algorithm will continue to loop. We will want to stop if cur or cur.next does not exist because that would mean we have reached the end of the list, and therefore do not need to keep looping. Inside the while loop is the following:

```python
val = cur.next.val
if cur.val < val:
cur = cur.next
continue
if p.next.val > val:
p = dummy
while p.next.val < val:
p = p.next
new = cur.next
cur.next = new.next
new.next = p.next
p.next = new
```

We will now begin to break it into pieces to explain what each and every part of the code does.

```python
val = cur.next.val
if cur.val < val:
cur = cur.next
continue
```

The first line here basically assigns the current val to be the next val. Then, the first if statement compares the current val with the next val. If the current val is less than the next val, then that part of the list is already sorted so we can move on by making cur go onto the next node via `cur=cur.next` and have the while loop continue iterating via `continue`.

```python
if p.next.val > val:
p = dummy
```

The second if statement checks if there is an element which is smaller than previous. If there is, you make `p` be dummy in order to find a proper postion to insert the smaller element.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
The second while loop is there to iterate through `p`:

```python
while p.next.val < val:
p = p.next
```

Basically, while the next value of `p` is less than the next value of `cur`, then the current `p` will change to become the next p. As a result, `p` will only stop at the element which is smaller than `val`.

```python
new = cur.next
cur.next = new.next
new.next = p.next
p.next = new
```

These 4 lines of code are here for the swapping and insertion part of the algorithm. The first line is basically the temporary variable that allows us to swap values. The second line is there to concatenate the elements in the sorted sequence. The third line is `new.next` being assigned to `p.next`. What this means is that it is swapping the values of `cur.next.next` with `p.next`. The fourth line is there to swap the next value of `p` with the next current value of `cur`.

Finally, we return `dummy.next` to return the sorted list.

Therefore, the solution should look like this:

```python
def insertionSortList(self, head):
p = dummy = ListNode(0)
cur = dummy.next = head
while cur and cur.next:
val = cur.next.val
if cur.val < val:
cur = cur.next
continue
if p.next.val > val:
p = dummy
while p.next.val < val:
p = p.next
new = cur.next
cur.next = new.next
new.next = p.next
p.next = new
return dummy.next
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
**Worst Case**

The worst case time complexity for the solution we made is O(n^2). This is because the worst case scenario is when the sorted linked list is reversed. Then that would mean that we would have to manually sort **all** of the elements in the linked list one by one. Therfore, we would have to use the first while loop and the second while loop inside the first one to their full potential, resulting in O(n^2).



**Average and Best Case**

The best case scenario would be when the linked list is already sorted. In thay case, our time complexity would be O(n) because regardless of whether or not the linked list is sorted, our solution will still have to go through all the elements in the linked list once to check if it is sorted or not. Both the best case and worst case scenarios are highly unlikely, and the most likely scenario to happen is mixture of both where some parts of the linked list is sorted while the other parts are not. Therefore, we will still have to use the second while loop in our solution, resulting in O(n^2) as our average time complexity.



**Space Complexity**

The space complexity of the algorithm is O(n). That is because the algorithm uses a linked list in its solution, thus giving us O(n). And since that is the biggest variable in terms of space complexity, then we can ignore all other constants.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
##Test Cases

**Example 1:**

```
Input: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
output: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
```

**Example 2:**

```
Input: 7 -> 3 -> 2 -> 1 -> 9 -> 15 -> 20
output: 1 -> 2 -> 3 -> 7 -> 9 -> 15 -> 20
```

**Example 3:**

```
Input: 50->45->30->27->19->15->10
output:10->15->19->27->30->45->50
```

**Example 4:**

```
Input: 8->9->5->4->10->11->19->20->1->2
output: 1->2->4->5->8->9->10->11->19->20
```

This file was deleted.

This file was deleted.

Loading