In-place vs extra memory Analyze by counting compares and exchanges(array accesses)
Iterative and in-place sorting algorithm that divides the data structure in two sublists: the ordered one, and the unordered one
Selection sort uses ~n2/2 compares and n exchanges to sort an array of length n.
Scenario | Complexity |
---|---|
Average | O(n^2) |
Best | O(n^2) |
Worst | O(n^2) |
Space | O(1) |
public void sortArray(int[] input) {
System.out.println("Selection Sort - ");
for (int i = 0; i <= input.length - 2; i++) { // last element will be already sorted when we finish for second last
int minIndex = i;
int curr = input[i];
for (int j = i + 1; j <= input.length - 1; j++) {
if (input[j] < input[minIndex]) { // we compare everytime hence O(n^2) in total
minIndex = j;
}
}
input[i] = input[minIndex]; //we swap only once per one outer loop hence n exchange
input[minIndex] = curr;
}
}
Divides the data structure in two sublists: a sorted one, and one still to sort.
Initially, the sorted sublist is made up of just one element and it gets progressively filled.
For every iteration, the algorithm picks an element on the unsorted sublist and inserts it at the right place in the sorted sublist
Scenario | Complexity |
---|---|
Average | O(n^2) |
Best | O(n) |
Worst | O(n^2) |
Space Complexity | O(1) |
For randomly ordered arrays of length N with with distinct keys, insertion sort uses ~N2/4 compares and ~N2/4 exchanges on the average. The worst case is ~ N2/2 compares and ~ N2/2 exchanges and the best case is N-1 compares and 0 exchanges.
public void sortArray(int[] input) {
System.out.println("Insertion Sort - ");
for (int i = 0; i < input.length; i++) {
int j = i;
while (j > 0 && input[j - 1] > input[j]) { // if its sorted array then this while block will not be executed making only N compares and no exchanges hence O(N)
int temp = input[j - 1];
input[j - 1] = input[j]; //worst case we always compare and exchange for every element with others at every iteration, hence O(n^2)
input[j] = temp;
j--;
}
}
}
Iterative sorting algorithm that imitates the movement of bubbles in sparkling water.
The bigger bubbles reach the top faster than smaller bubbles, and this algorithm works in the same way.
It iterates through the data structure and for each cycle compares the current element with the next one, swapping them if they are in the wrong order.
We can do small optimization when on the a complete iteration of inner loop while outer loop is on first iteration, if no swapping was done, we can break since we know its a sorted array(Best time complexity scenario)
Scenario | Complexity |
---|---|
Average | O(n^2) |
Best | O(n) |
Worst | O(n^2) |
Space Complexity | O(1) |
public void sortArray(int[] input) {
System.out.println("Bubble Sort - ");
for (int i = input.length - 1; i >= 1; i--) {
boolean swapHappened = false;
for (int j = 0; j <= i - 1; j++) {
if (input[j] > input[j + 1]) {
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
swapHappened = true;
}
}
if (!swapHappened) {
// if no swap happened on first pass, we know its sorted array
// no need to check and compare further
System.out.println("No swapping so we break " + i);
break;
}
}
}
Out of place algorithm since we need extra array to merge n/2 two arrays on each sub-step
Uses divide and conquer where we divide given array into two parts.
Combine two ordered arrays to make one larger ordered array.
Can be implemented iteratively or recursively, using the Top-Down and Bottom-Up algorithms respectively
Scenario | Complexity |
---|---|
Average | O(nlogn) |
Best | O(nlogn) |
Worst | O(nlogn) |
Space Complexity | O(n) |
public void sortArray(int[] input) {
System.out.println("Merge Sort - ");
sort(input, 0, input.length - 1);
}
private void merge(int[] arr, int left, int mid, int right) {
int leftP = left;
int rightP = mid + 1;
int[] dummy = new int[right + 1];
int dummyIndex = 0;
while (leftP <= mid && rightP <= right) {
if (arr[leftP] < arr[rightP]) {
dummy[dummyIndex++] = arr[leftP++];
} else {
dummy[dummyIndex++] = arr[rightP++];
}
}
while (leftP <= mid) {
dummy[dummyIndex++] = arr[leftP++];
}
while (rightP <= right) {
dummy[dummyIndex++] = arr[rightP++];
}
dummyIndex = 0;
for (int i = left; i <= right; i++) {
arr[i] = dummy[dummyIndex++];
}
}
public void sort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
sort(arr, left, mid);
sort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
Also uses divide and conquer
In place algorithm unlike merge sort
Divide in smaller partitions and sort them recursively until the data structure is sorted.
Scenario | Complexity |
---|---|
Average | O(nlogn) |
Best | O(nlogn) |
Worst | O(n^2) |
Space Complexity | O(1) |
public class QuickSort {
public void sortArray(int[] input) {
quickSort(input, 0, indx);
}
public int partition(int nums[], int left, int right) {
int pivot = nums[right]; //consider the last element is pivot for us
int i = left - 1;
while (left < right) {
if (nums[left] < pivot) {
int temp = nums[left];
nums[left] = nums[++i];
nums[i] = temp;
}
left++;
}
int temp = nums[i + 1];
nums[i + 1] = pivot;
nums[right] = temp;
return i + 1;
}
public void quickSort(int[] input, int left, int right) {
if (left < right) {
int partition = partition(input, left, right);
quickSort(input, left, partition - 1);
quickSort(input, partition + 1, right);
}
}
}
| Implement pow(x,n) | Implement pow(x, n), which calculates x raised to the power n (i.e., xn). Input Output x = 2.00000, n = 10 1024.00000 x = 2.10000, n = 3 9.26100 x = 2.00000, n = -2 0.25000 Notes Brute Force Approach 2^ 12 = 2 * 2^11 = 2* 2* 2^10 and so on.. This takes O(n) and could be...
read more