diff --git a/Exercise_1.java b/Exercise_1.java index c3ff1141..3b359fd0 100644 --- a/Exercise_1.java +++ b/Exercise_1.java @@ -1,8 +1,24 @@ +// Time Complexity : O(logN) +// Space Complexity : O(1) +// Did this code successfully run on Leetcode : Yes +// Any problem you faced while coding this : Yes. Initially in line 15, I added x < mid instead of x < arr[mid] and it failed on Leetcode. Fixed it later. class BinarySearch { // Returns index of x if it is present in arr[l.. r], else return -1 int binarySearch(int arr[], int l, int r, int x) { //Write your code here + while (l < r) { + int mid = (l + r) / 2; + if (x == arr[mid]) { + return mid; + } + if (x < arr[mid]) { + r = mid - 1; + } else { + l = mid + 1; + } + } + return -1; } // Driver method to test above diff --git a/Exercise_2.java b/Exercise_2.java index d0b5fa5f..59e1056d 100644 --- a/Exercise_2.java +++ b/Exercise_2.java @@ -1,3 +1,7 @@ +// Time Complexity : O(NlogN) +// Space Complexity : O(logN). Space for the recursive call. +// Did this code successfully run on Leetcode : No, did not find it on Leetcode. +// Any problem you faced while coding this : Yes, I had to watch some youtube videos to recollect quick sort. class QuickSort { /* This function takes last element as pivot, @@ -8,11 +12,30 @@ class QuickSort of pivot */ void swap(int arr[],int i,int j){ //Your code here + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; } int partition(int arr[], int low, int high) { //Write code here for Partition and Swap + // Taking the last element as pivot. + int pivot = arr[high]; + int i = low - 1; + // Place all elements less than pivot on the left side of the array. + for (int j = low; j < high; j ++) { + if (arr[j] <= pivot) { + i ++; + swap(arr, i, j); + } + } + // Place pivot in the partition index, + // where all elements on the left are less than pivot + // and all elements on the right are greater than the pivot. + swap(arr, i + 1, high); + // Return pivot index. + return i + 1; } /* The main function that implements QuickSort() arr[] --> Array to be sorted, @@ -20,8 +43,17 @@ int partition(int arr[], int low, int high) high --> Ending index */ void sort(int arr[], int low, int high) { - // Recursively sort elements before - // partition and after partition + // Recursively sort elements before + // partition and after partition + if (low < high) { + int pivotIndex = partition(arr, low, high); + if (pivotIndex - 1 > low) { + sort(arr, low, pivotIndex - 1); // left partition + } + if (pivotIndex + 1 < high) { + sort(arr, pivotIndex + 1, high); // right partition + } + } } /* A utility function to print array of size n */ diff --git a/Exercise_3.java b/Exercise_3.java index 1f9b752a..9ab65f59 100644 --- a/Exercise_3.java +++ b/Exercise_3.java @@ -1,3 +1,7 @@ +// Time Complexity : O(N) +// Space Complexity : O(1) +// Did this code successfully run on Leetcode : Yes +// Any problem you faced while coding this : No class LinkedList { Node head; // head of linked list @@ -20,6 +24,13 @@ void printMiddle() { //Write your code here //Implement using Fast and slow pointers + Node slow = head; + Node fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + System.out.println(slow.data); } public void push(int new_data) diff --git a/Exercise_4.java b/Exercise_4.java index 81afd3c2..f8497faf 100644 --- a/Exercise_4.java +++ b/Exercise_4.java @@ -1,3 +1,7 @@ +// Time Complexity : O(NlogN) +// Space Complexity : O(N). Space used for leftHalf and rightHalf arrays. +// Did this code successfully run on Leetcode : No, did not find it on Leetcode. +// Any problem you faced while coding this : Yes, I had to watch some youtube videos to recollect merge sort. class MergeSort { // Merges two subarrays of arr[]. @@ -6,6 +10,39 @@ class MergeSort void merge(int arr[], int l, int m, int r) { //Your code here + int leftSize = m - l + 1; // Since arr is 0 indexed, used "+ 1" to get the correct size. + int rightSize = r - m; // m index is already included in the leftSize, so no need of "+ 1" here. + int[] leftHalf = new int[leftSize]; + int[] rightHalf = new int[rightSize]; + // Copy left half of arr into leftHalf[] + for (int x = 0; x < leftSize; x++) { + leftHalf[x] = arr[l + x]; + } + // Copy right half of arr into rightHalf[] + for (int i = 0; i < rightSize; i++) { + rightHalf[i] = arr[m + 1 + i]; + } + int i = 0; // index to iterate through leftHalf[] + int j = 0; // index to iterate through rightHalf[] + int k = l; // index to iterate through arr + // Compare elements in leftHalf with rightHalf and add in the ascending order in arr. + // Note that the leftHalf and rightHalf are already sorted subarrays. + while (i < leftSize && j < rightSize) { + if (leftHalf[i] <= rightHalf[j]) { + arr[k ++] = leftHalf[i ++]; + } else { + arr[k ++] = rightHalf[j ++]; + } + } + + // Add the remaining elements from left partition to arr, which is already sorted. + while (i < leftSize) { + arr[k ++] = leftHalf[i ++]; + } + // Add the remaining elements from right partition to arr, which is already sorted. + while (j < rightSize) { + arr[k ++] = rightHalf[j ++]; + } } // Main function that sorts arr[l..r] using @@ -13,7 +50,16 @@ void merge(int arr[], int l, int m, int r) void sort(int arr[], int l, int r) { //Write your code here - //Call mergeSort from here + if (l < r) { + int m = (l + r) / 2; // find mid + // Keep partitioning the left subarray in a recursive way and then merge by sorting. + sort(arr, l, m); + // Keep partitioning the right subarray in a recursive way and then merge by sorting. + sort(arr, m + 1, r); + //Call mergeSort from here + // Merge left and right partitions/subarrays in ascending order of the elements. + merge(arr, l, m, r); + } } /* A utility function to print array of size n */ diff --git a/Exercise_5.java b/Exercise_5.java index 30e82675..27fb996a 100644 --- a/Exercise_5.java +++ b/Exercise_5.java @@ -1,20 +1,67 @@ +// Time Complexity : O(NlogN) +// Space Complexity : O(1) +// Did this code successfully run on Leetcode : No, did not find it on Leetcode. +// Any problem you faced while coding this : No, working on recursive approach first helped. +import java.util.Stack; class IterativeQuickSort { void swap(int arr[], int i, int j) { //Try swapping without extra variable + if (i == j || arr[i] == arr[j]) { + // The value of XOR of two same numbers will be 0. + return; + } + arr[i] = arr[i] ^ arr[j]; + arr[j] = arr[i] ^ arr[j]; // = (arr[i] ^ arr[j]) ^ arr[j] = arr[i] + arr[i] = arr[i] ^ arr[j]; // = (arr[i] ^ arr[j]) ^ arr[i] = arr[j] } /* This function is same in both iterative and recursive*/ int partition(int arr[], int l, int h) { - //Compare elements and swap. + // Taking the last element as pivot. + int pivot = arr[h]; + int i = l - 1; + // Place all elements less than pivot on the left side of the array. + for (int j = l; j < h; j ++) { + if (arr[j] <= pivot) { + i ++; + swap(arr, i, j); + } + } + // Place pivot in the partition index, + // where all elements on the left are less than pivot + // and all elements on the right are greater than the pivot. + swap(arr, i + 1, h); + // Return pivot index. + return i + 1; } // Sorts arr[l..h] using iterative QuickSort void QuickSort(int arr[], int l, int h) { //Try using Stack Data Structure to remove recursion. + Stack stack = new Stack<>(); + stack.push(l); + stack.push(h); + while (!stack.isEmpty()) { + h = stack.pop(); // h index will be popped first + l = stack.pop(); + if (l < h) { + int pivotIndex = partition(arr, l, h); + if (pivotIndex - 1 > l) { + // Consider the left subarray and push the indices to the stack. + stack.push(l); + stack.push(pivotIndex - 1); + } + if (pivotIndex + 1 < h) { + // Consider the right subarray and push the indices to the stack. + stack.push(pivotIndex + 1); + stack.push(h); + } + } + } } // A utility function to print contents of arr