├── src └── org │ └── programming │ └── mitra │ └── exercises │ ├── StringImmutabilityExample.java │ ├── logics │ ├── LongestIncreasingSubsequence.java │ ├── FindAllSubStrings.java │ ├── KthSmallestNumber.java │ ├── TwoElementSumInSortedArray.java │ ├── TwoElementSumInArray.java │ ├── LinkedListRotation.java │ ├── MultiplyTwoNumbersInStringForm.java │ ├── AddTwoNumbersInLinkedListForm.java │ └── MaximumSubArraySum.java │ ├── ClassNotFoundExceptionExample.java │ ├── IntegerCacheExample.java │ ├── algos │ ├── sort │ │ └── MergeSort.java │ ├── graph │ │ ├── mst │ │ │ ├── PrimsAlgorithm.java │ │ │ ├── KruskalsAlgoWithParentDS.java │ │ │ ├── KruskalsAlgoWithNameDS.java │ │ │ ├── KruskalsAlgoWithParentDSAndSizeAndPathCompression.java │ │ │ ├── PrimsAlgorithmWithHeap.java │ │ │ └── KruskalsAlgoWithParentDSAndSize.java │ │ ├── apsp │ │ │ └── FloydWarshallAlgorithm.java │ │ ├── sssp │ │ │ └── DijkstraAlgorithm.java │ │ └── dag │ │ │ └── TopologicalSortAndLongestPath.java │ └── cryptography │ │ └── RSA_Algorithm.java │ ├── LambdaExpression.java │ ├── OverridingInternalExample.java │ ├── OverloadingOverridingExample.java │ ├── VariableShadowingExample.java │ ├── ImmutableClassExample.java │ ├── ObjectCreation.java │ ├── CopyConstructorExample.java │ ├── DeepCloningUsingSerializationExample.java │ ├── SerializationExample.java │ ├── ExternalizableExample.java │ ├── CloningExample.java │ └── ds │ └── RedBlackTree.java ├── srcpy ├── water-in-bar-graph.py ├── product-array-puzzle.py └── minimum-steps.py ├── .gitignore └── readme.md /src/org/programming/mitra/exercises/StringImmutabilityExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * @author Naresh Joshi 7 | * 8 | * See complete articles on below links 9 | * 10 | * https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html, 11 | * https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html 12 | */ 13 | public class StringImmutabilityExample { 14 | public static void main(String[] args) throws Exception { 15 | 16 | String string = "Naresh"; 17 | 18 | Class type = String.class; 19 | Field field = type.getDeclaredField("value"); 20 | field.setAccessible(true); 21 | 22 | char[] value = (char[]) field.get(string); 23 | value[0] = 'M'; 24 | 25 | System.out.println(string); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /srcpy/water-in-bar-graph.py: -------------------------------------------------------------------------------- 1 | def countWater(array) : 2 | 3 | n = len(array) 4 | 5 | max_left_list = [-1] * n 6 | max_right_list = [-1] * n 7 | 8 | print(max_left_list) 9 | print(max_right_list) 10 | print() 11 | 12 | max_left = array[0] 13 | max_right = array[-1] 14 | 15 | i = 1 16 | j = n-2 17 | 18 | while i < n or j > 0 : 19 | 20 | max_left = max(array[i-1], max_left) 21 | max_left_list[i] = max_left; 22 | i = i + 1 23 | 24 | max_right = max(array[j+1], max_right) 25 | max_right_list[j] = max_right 26 | j = j - 1 27 | 28 | print(max_left_list) 29 | print(max_right_list) 30 | print() 31 | 32 | total_quantity = 0 33 | for count in range(1, n-1) : 34 | quantity = min(max_left_list[count], max_right_list[count]) - array[count]; 35 | total_quantity += quantity 36 | print(f'{count} {max_left_list[count]} {max_right_list[count]} {quantity} {total_quantity}') 37 | 38 | return total_quantity 39 | 40 | 41 | print(countWater([5, 1, 3, 4, 5])) -------------------------------------------------------------------------------- /srcpy/product-array-puzzle.py: -------------------------------------------------------------------------------- 1 | def printProductArray(array) : 2 | n = len(array) 3 | 4 | left_product_array = [1] * n 5 | right_product_array = [1] * n 6 | 7 | i = 1 8 | j = n-2 9 | 10 | while i < n and j >= 0: 11 | print(left_product_array) 12 | print() 13 | print(right_product_array) 14 | print() 15 | left_product_array[i] = left_product_array[i-1] * array[i-1] 16 | right_product_array[j] = right_product_array[j+1] * array[j+1] 17 | i = i+1 18 | j = j-1 19 | 20 | print(left_product_array) 21 | print() 22 | print(right_product_array) 23 | print() 24 | 25 | final_array = [1] * n 26 | i = 0 27 | for count in range(n): 28 | final_array[count] = left_product_array[count] * right_product_array[count] 29 | 30 | return final_array 31 | 32 | 33 | print(printProductArray([10, 3, 5, 6, 2])) 34 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/LongestIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | public class LongestIncreasingSubsequence { 4 | public static void main(String[] args) { 5 | int[] arr = new int[]{7, 4, 1, 8, 2, 9, 3, 6, 0, 10}; 6 | findLongestIncreasingSubsequence(arr); 7 | } 8 | 9 | private static void findLongestIncreasingSubsequence(int[] arr) { 10 | int longestIncrSubSeqLength = 0; 11 | for (int i = 0; i < arr.length; i++) { 12 | int incrSubSeqLength = 0; 13 | int lastBigDigit = arr[i]; 14 | for (int j = i + 1; j < arr.length; j++) { 15 | if (arr[j] > lastBigDigit) { 16 | lastBigDigit = arr[j]; 17 | incrSubSeqLength++; 18 | } 19 | } 20 | 21 | longestIncrSubSeqLength = Math.max(longestIncrSubSeqLength, incrSubSeqLength); 22 | } 23 | 24 | System.out.println(longestIncrSubSeqLength); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/ClassNotFoundExceptionExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * See complete article on below link 7 | * 8 | * https://www.programmingmitra.com/2017/04/Difference-Between-ClassNotFoundException-and-NoClassDefFoundError.html 9 | */ 10 | public class ClassNotFoundExceptionExample { 11 | public static void main(String[] args) throws Exception { 12 | 13 | // NoClassDefFoundError Example 14 | // Do javac on ClassNotFoundExceptionExample.java, 15 | // Program will compile successfully because Employee class exits 16 | // Manually delete Employee.class file 17 | // Run the program using java ClassNotFoundExceptionExample 18 | Employee emp = new Employee(); 19 | emp.saySomething(); 20 | 21 | // ClassNotFoundException Example 22 | // Provide any class to Class.forName() which doe not exist 23 | // Or compile ClassNotFoundExceptionExample.java and then manually delete Person.class file so Person class will become unavailable 24 | // Run the program using java ClassNotFoundExceptionExample 25 | Class personClass = Class.forName("Person"); 26 | Person person = (Person) personClass.newInstance(); 27 | person.saySomething(); 28 | } 29 | 30 | static class Employee { 31 | void saySomething() { 32 | System.out.println("Hello"); 33 | } 34 | } 35 | 36 | static class Person { 37 | void saySomething() { 38 | System.out.println("Hello"); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/FindAllSubStrings.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | // SubStrings or SubArrays of 1234 are 1,12,123,1234,2,23,234,3,34,4 4 | // An string of size n can have n*(n+1)/2 substrings 5 | public class FindAllSubStrings { 6 | public static void main(String[] args) { 7 | String input = "12345"; 8 | 9 | System.out.print("\nAll substrings of given string are:\n"); 10 | findAllSubArrays(input.toCharArray()); 11 | 12 | System.out.print("\nAll substrings of given string are:\n"); 13 | findAllSubArraysRecursively(input.toCharArray(), 0, 0); 14 | } 15 | 16 | // Complexity - O(n^3) 17 | private static void findAllSubArrays(char[] arr) { 18 | for (int i = 0; i < arr.length; i++) { 19 | for (int j = i; j < arr.length; j++) { 20 | for (int k = i; k <= j; k++) { 21 | System.out.print(arr[k]); 22 | } 23 | System.out.print(" "); 24 | } 25 | } 26 | } 27 | 28 | // Complexity - O(n^3) 29 | private static void findAllSubArraysRecursively(char[] arr, int start, int end) { 30 | if (start == arr.length) { 31 | return; 32 | } else if (end == arr.length) { 33 | findAllSubArraysRecursively(arr, start + 1, start + 1); 34 | } else { 35 | for (int i = start; i <= end; i++) { 36 | System.out.print(arr[i]); 37 | } 38 | System.out.print(" "); 39 | 40 | findAllSubArraysRecursively(arr, start, end + 1); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/IntegerCacheExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * Java Integer Cache - Why Integer.valueOf(127) == Integer.valueOf(127) Is True 7 | * 8 | * See complete article on below link 9 | * 10 | * https://www.programmingmitra.com/2018/11/java-integer-cache.html 11 | */ 12 | public class IntegerCacheExample { 13 | public static void main(String[] args) { 14 | // For Value 128 15 | 16 | // Operation == on two primitive types with same value returns true because both holds same value 17 | int a = 128; 18 | int b = 128; 19 | System.out.println(a == b); // Output -- true 20 | 21 | // Operation == on two reference types with same value returns false because both are different objects with different addresses 22 | Integer aObj = 128; 23 | Integer bObj = 128; 24 | System.out.println(aObj == bObj); // Output -- false 25 | 26 | System.out.println(aObj.equals(bObj)); // Output -- true 27 | 28 | // For value 127 29 | int x = 127; 30 | int y = 127; 31 | System.out.println(x == y); // Output -- true 32 | 33 | Integer xObj = Integer.valueOf(127); // Auto boxing example, compiler converts it to Integer c = Integer.valueOf(128); 34 | Integer yObj = 127; // Compiler converts it to Integer d = Integer.valueOf(128); 35 | System.out.println(xObj == yObj); // Output -- true 36 | 37 | // Output of above line is true because Integer class caches integer objects which falls in range -128 to 127, 38 | // and returns same object for every autoboxing invocation 39 | 40 | System.out.println(xObj.equals(yObj)); // Output -- true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/KthSmallestNumber.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | import java.util.Arrays; 4 | 5 | public class KthSmallestNumber { 6 | public static void main(String[] args) { 7 | int[] arr = {2, 9, 4, 6, 5, 3, 0, 1, 8, 10}; 8 | System.out.println(findKthSmallestNumberUsingDnC(arr, 0, arr.length - 1, 9)); 9 | } 10 | 11 | // Finding kth smallest item using divide and conquer 12 | private static int findKthSmallestNumberUsingDnC(int[] arr, int start, int end, int k) { 13 | int i = start; 14 | int j = end; 15 | int p = (start + end) / 2; 16 | 17 | System.out.println(); 18 | System.out.println("For pivot " + arr[p]); 19 | 20 | while (j >= i) { 21 | if (p > i && arr[p] < arr[i]) { 22 | swap(arr, i, p); 23 | p = i; 24 | } 25 | i++; 26 | 27 | if (p < j && arr[p] > arr[j]) { 28 | swap(arr, p, j); 29 | p = j; 30 | } 31 | j--; 32 | System.out.println(Arrays.toString(arr)); 33 | } 34 | 35 | System.out.println(Arrays.toString(arr)); 36 | 37 | int lengthOfArrBeforePivot = p - start; 38 | if (lengthOfArrBeforePivot == k - 1) { 39 | return arr[p]; 40 | } else if (lengthOfArrBeforePivot > k - 1) { 41 | return findKthSmallestNumberUsingDnC(arr, start, lengthOfArrBeforePivot, k); 42 | } else { 43 | return findKthSmallestNumberUsingDnC(arr, p + 1, end, k - lengthOfArrBeforePivot - 1); 44 | } 45 | } 46 | 47 | static void swap(int[] arr, int i, int j) { 48 | System.out.println("Swapping " + arr[i] + " with " + arr[j]); 49 | int temp = arr[i]; 50 | arr[i] = arr[j]; 51 | arr[j] = temp; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | public class MergeSort { 6 | public static void main(String[] args) { 7 | int[] arr = {6, 5, 1, 7, 8, 2, 4, 3, 2, 9, 1}; 8 | System.out.println(Arrays.toString(arr)); 9 | 10 | int[] temp = new int[arr.length]; 11 | mergeSort(arr, temp, 0, arr.length - 1); 12 | 13 | System.out.println(Arrays.toString(arr)); 14 | System.out.println(Arrays.toString(temp)); 15 | } 16 | 17 | public static void mergeSort(int[] arr, int[] temp, int start, int end) { 18 | if (end <= start) { 19 | return; 20 | } 21 | 22 | int mid = (start + end) / 2; 23 | 24 | mergeSort(arr, temp, start, mid); 25 | mergeSort(arr, temp, mid + 1, end); 26 | 27 | mergeHalves(arr, temp, start, mid, end); 28 | } 29 | 30 | public static void mergeHalves(int[] arr, int[] temp, int start, int mid, int end) { 31 | int i = start; 32 | int j = mid + 1; 33 | int k = start; 34 | 35 | // Comparing items from both halves and copying in order 36 | while (i <= mid && j <= end) { 37 | if (arr[i] < arr[j]) { 38 | temp[k++] = arr[i++]; 39 | } else { 40 | temp[k++] = arr[j++]; 41 | } 42 | } 43 | 44 | // Copying remaining first halve 45 | while (i <= mid) { 46 | temp[k++] = arr[i++]; 47 | } 48 | 49 | // Copying remaining second halve 50 | while (j <= end) { 51 | temp[k++] = arr[j++]; 52 | } 53 | 54 | // Copying temp array back to actual array so it will be reflected in other recursive calls 55 | for (i = 0; i <= end; i++) { 56 | arr[i] = temp[i]; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/TwoElementSumInSortedArray.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | 6 | public class TwoElementSumInSortedArray { 7 | 8 | public static void main(String[] args) { 9 | int[] arr = new int[]{2, 7, 11, 15}; 10 | System.out.println(Arrays.toString(twoSumInOnePassUsingMap(arr, 9))); 11 | System.out.println(Arrays.toString(twoSumInOnePassUsingTwoPointers(arr, 9))); 12 | 13 | arr = new int[]{2, 3, 4}; 14 | System.out.println(Arrays.toString(twoSumInOnePassUsingMap(arr, 6))); 15 | System.out.println(Arrays.toString(twoSumInOnePassUsingTwoPointers(arr, 6))); 16 | 17 | arr = new int[]{3, 3}; 18 | System.out.println(Arrays.toString(twoSumInOnePassUsingMap(arr, 6))); 19 | System.out.println(Arrays.toString(twoSumInOnePassUsingTwoPointers(arr, 6))); 20 | } 21 | 22 | public static int[] twoSumInOnePassUsingMap(int[] arr, int target) { 23 | HashMap map = new HashMap<>(); 24 | for (int i = 0; i < arr.length && arr[i] < target; i++) { 25 | int diff = target - arr[i]; 26 | Integer match = map.get(diff); 27 | if (match != null) { 28 | return new int[]{match, i}; 29 | } 30 | map.put(arr[i], i); 31 | } 32 | return null; 33 | } 34 | 35 | public static int[] twoSumInOnePassUsingTwoPointers(int[] arr, int target) { 36 | int left = 0, right = arr.length - 1; 37 | while (left < right) { 38 | int sum = arr[left] + arr[right]; 39 | if (sum == target) { 40 | return new int[]{left, right}; 41 | } else if (sum < target) { 42 | left++; 43 | } else { 44 | right--; 45 | } 46 | } 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/TwoElementSumInArray.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | 6 | public class TwoElementSumInArray { 7 | 8 | public static void main(String[] args) { 9 | int[] arr = new int[]{2, 7, 11, 15}; 10 | System.out.println(Arrays.toString(twoSumTwoPass(arr, 9))); 11 | System.out.println(Arrays.toString(twoSumOnePass(arr, 9))); 12 | 13 | arr = new int[]{3, 4, 2}; 14 | System.out.println(Arrays.toString(twoSumTwoPass(arr, 6))); 15 | System.out.println(Arrays.toString(twoSumOnePass(arr, 6))); 16 | 17 | arr = new int[]{3, 3}; 18 | System.out.println(Arrays.toString(twoSumTwoPass(arr, 6))); 19 | System.out.println(Arrays.toString(twoSumOnePass(arr, 6))); 20 | } 21 | 22 | public static int[] twoSumTwoPass(int[] arr, int target) { 23 | int[] result = new int[2]; 24 | 25 | HashMap map = new HashMap<>(); 26 | for (int i = 0; i < arr.length; i++) { 27 | map.put(arr[i], i); 28 | arr[i] = target - arr[i]; 29 | } 30 | 31 | for (int i = 0; i < arr.length; i++) { 32 | Integer match = map.get(arr[i]); 33 | if (match != null && i != match) { 34 | result[0] = i; 35 | result[1] = match; 36 | 37 | return result; 38 | } 39 | } 40 | return null; 41 | } 42 | 43 | public static int[] twoSumOnePass(int[] arr, int target) { 44 | HashMap map = new HashMap<>(); 45 | for (int i = 0; i < arr.length; i++) { 46 | int diff = target - arr[i]; 47 | Integer match = map.get(diff); 48 | if (match != null) { 49 | return new int[]{match, i}; 50 | } 51 | map.put(arr[i], i); 52 | } 53 | return null; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/LinkedListRotation.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | public class LinkedListRotation 4 | { 5 | public static void main(String[] args) 6 | { 7 | Node n1 = new Node<>(1); 8 | Node n2 = new Node<>(2); 9 | Node n3 = new Node<>(3); 10 | Node n4 = new Node<>(4); 11 | Node n5 = new Node<>(5); 12 | Node n6 = new Node<>(6); 13 | Node n7 = new Node<>(7); 14 | Node n8 = new Node<>(8); 15 | 16 | Node head = n1; 17 | n1.next = n2; 18 | n2.next = n3; 19 | n3.next = n4; 20 | n4.next = n5; 21 | n5.next = n6; 22 | n6.next = n7; 23 | n7.next = n8; 24 | 25 | System.out.println(transform(head, 6)); 26 | } 27 | 28 | private static Node transform(Node start, int k) 29 | { 30 | Node next = start; 31 | for (int i = 1; i < k && next != null; i++) 32 | { 33 | next = next.next; 34 | } 35 | 36 | if (next == null) 37 | { 38 | return start; 39 | } 40 | 41 | int count = 1; 42 | Node beg; 43 | Node end = start; 44 | while (count < k && end.next != null) 45 | { 46 | beg = start; 47 | start = end.next; 48 | end.next = start.next; 49 | start.next = beg; 50 | count++; 51 | System.out.println(start); 52 | } 53 | 54 | end.next = transform(end.next, k); 55 | 56 | return start; 57 | } 58 | } 59 | 60 | class Node 61 | { 62 | T value; 63 | Node next; 64 | 65 | public Node(T value) 66 | { 67 | this.value = value; 68 | } 69 | 70 | public Node(T value, Node next) 71 | { 72 | this.value = value; 73 | this.next = next; 74 | } 75 | 76 | @Override 77 | public String toString() 78 | { 79 | return value + ((next == null) ? "" : "->" + next); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/LambdaExpression.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.awt.Button; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.util.Comparator; 7 | import java.util.function.Consumer; 8 | import java.util.stream.IntStream; 9 | 10 | /** 11 | * @author Naresh Joshi 12 | * 13 | * See complete article on below link 14 | * 15 | * https://www.programmingmitra.com/2016/06/java-lambda-expression-explained-with-example.html 16 | */ 17 | public class LambdaExpression { 18 | 19 | @SuppressWarnings("unused") 20 | public static void main(String[] args) { 21 | 22 | // Example : Thread Creation 23 | // Old Way 24 | Runnable runnable = new Runnable() { 25 | @Override 26 | public void run() { 27 | System.out.println("Running thread using anonymous class"); 28 | } 29 | }; 30 | Thread thread = new Thread(runnable); 31 | thread.start(); 32 | 33 | // New Way 34 | runnable = () -> System.out.println("Running thread using lambda expression"); 35 | thread = new Thread(runnable); 36 | thread.start(); 37 | 38 | // Example : Comparator Creation 39 | Comparator comparator = (Integer i, Integer j) -> i.compareTo(j); 40 | 41 | // Example : Consumer Creation 42 | Consumer consumer = obj -> System.out.println(obj); 43 | 44 | // Example : Consumer Creation 45 | Button button = new Button(); 46 | 47 | // Old way: 48 | button.addActionListener(new ActionListener() { 49 | @Override 50 | public void actionPerformed(ActionEvent e) { 51 | System.out.println("button clicked"); 52 | } 53 | }); 54 | 55 | // New way: 56 | button.addActionListener((e) -> { 57 | System.out.println("button clicked"); 58 | }); 59 | 60 | // Example : Iteration 61 | System.out.println("####### Old way #######"); 62 | for (int i = 1; i < 10; i++) { 63 | int j = i * i; 64 | System.out.println(j); 65 | } 66 | 67 | System.out.println("####### Lambda(Stream) way #######"); 68 | IntStream.range(1, 10) 69 | .map(num -> num * num) 70 | .forEach(i -> System.out.println(i)); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/OverridingInternalExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * See complete articles on below links 7 | * 8 | * https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html, 9 | * https://www.programmingmitra.com/2017/05/everything-about-method-overloading-vs-method-overriding.html, 10 | * https://www.programmingmitra.com/2017/12/why-we-should-follow-method-overriding-rules.html, 11 | * https://www.programmingmitra.com/2018/11/why-instance-variable-of-super-class-is-not-overridden-In-sub-class.html 12 | */ 13 | public class OverridingInternalExample { 14 | 15 | private static class Mammal { 16 | public void speak() { System.out.println("Well might speak something like ohlllalalalalalaoaoaoa"); } 17 | } 18 | 19 | private static class Human extends Mammal { 20 | 21 | @Override 22 | public void speak() { System.out.println("Hello"); } 23 | 24 | // Valid overload of speak 25 | public void speak(String language) { 26 | if (language.equals("Hindi")) System.out.println("Namaste"); 27 | else System.out.println("Hello"); 28 | } 29 | 30 | } 31 | 32 | public static void main(String[] args) { 33 | Mammal anyMammal = new Mammal(); 34 | anyMammal.speak(); // Output - Well might speak something like ohlllalalalalalaoaoaoa 35 | // 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V 36 | 37 | Mammal humanMammal = new Human(); 38 | humanMammal.speak(); // Output - Hello 39 | // 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V 40 | 41 | Human human = new Human(); 42 | human.speak(); // Output - Hello 43 | // 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V 44 | 45 | human.speak("Hindi"); // Output - Namaste 46 | // 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /srcpy/minimum-steps.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Program to calculate maximum steps require to make a number 1 from n while the steps we can take is 3 | subtract by 1, divide by 2 if divisible, divide by 3 if divisible 4 | ''' 5 | 6 | def get_min_steps_using_recursion(n): 7 | 8 | print('Solving minimum steps problem using recursion') 9 | 10 | if n == 1 : 11 | return 0 12 | 13 | print(f'number is {n} subtracting 1 now number becomes {n-1}') 14 | count = get_min_steps_using_recursion(n-1) 15 | 16 | if n % 2 == 0 : 17 | print(f'number is {n} dividing by 2 now number becomes {int(n/2)}') 18 | count = min(count, get_min_steps_using_recursion(int(n/2))) 19 | 20 | if n % 3 == 0 : 21 | print(f'number is {n} dividing by 3 now number becomes {int(n/3)}') 22 | count = min(count, get_min_steps_using_recursion(int(n/3))) 23 | 24 | return 1 + count 25 | 26 | 27 | def get_min_steps_using_memoization(n, memo = None): 28 | 29 | print('Solving minimum steps problem using memoization') 30 | 31 | if(memo is None) : 32 | memo = [-1] * (n+1) 33 | memo[1] = 0 34 | 35 | if memo[n] != -1 : 36 | return memo[n]; 37 | 38 | print(f'number is {n} subtracting 1 now number becomes {n-1}') 39 | count = get_min_steps_using_memoization(n-1, memo) 40 | 41 | if n % 2 == 0 : 42 | print(f'number is {n} dividing by 2 now number becomes {int(n/2)}') 43 | count = min(count, get_min_steps_using_memoization(int(n/2), memo)) 44 | 45 | if n % 3 == 0 : 46 | print(f'number is {n} dividing by 3 now number becomes {int(n/3)}') 47 | count = min(count, get_min_steps_using_memoization(int(n/3), memo)) 48 | 49 | memo[n] = 1 + count 50 | print(f'changing memo to {memo}') 51 | 52 | return memo[n] 53 | 54 | 55 | def get_min_steps_using_dp(n, dp = None): 56 | 57 | print('Solving minimum steps problem using tabulation') 58 | 59 | if(dp is None) : 60 | dp = [0] * (n+1) 61 | dp[1] = 0 62 | 63 | for i in range (2, n+1): 64 | 65 | print(f'number is {i} subtracting 1 now number becomes {i-1}') 66 | count = dp[i-1] 67 | 68 | if i % 2 == 0 : 69 | print(f'number is {i} dividing by 2 now number becomes {int(i/2)}') 70 | count = min(count, dp[int(i/2)]) 71 | 72 | if i % 3 == 0 : 73 | print(f'number is {i} dividing by 3 now number becomes {int(i/3)}') 74 | count = min(count, dp[int(i/3)]) 75 | 76 | dp[i] = 1 + count 77 | print(f'changing dp to {dp}') 78 | 79 | return dp[n] 80 | 81 | 82 | print(get_min_steps_using_recursion(10)) 83 | print(get_min_steps_using_memoization(10)) 84 | print(get_min_steps_using_dp(10)) -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/MultiplyTwoNumbersInStringForm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | public class MultiplyTwoNumbersInStringForm { 4 | public static void main(String[] args) { 5 | System.out.println(multiply("0", "0") + " == " + (0)); 6 | System.out.println(multiply("9234", "431") + " == " + (9234 * 431)); 7 | System.out.println(multiply("2", "6") + " == " + (2 * 6)); 8 | System.out.println(multiply("12", "3") + " == " + (12 * 3)); 9 | System.out.println(multiply("10", "890") + " == " + (10 * 890)); 10 | System.out.println(multiply("999", "99999") + " == " + (999 * 99999)); 11 | System.out.println(multiply("-999", "99999") + " == " + (-999 * 99999)); 12 | System.out.println(multiply("999", "-999999") + " == " + (999 * -999999)); 13 | System.out.println(multiply("-999", "-99999") + " == " + (-999 * -99999)); 14 | System.out.println(multiply("999", "999999") + " == " + (999 * 999999)); 15 | } 16 | 17 | public static String multiply(String num1, String num2) { 18 | 19 | boolean isNegative = false; 20 | if (num1.charAt(0) == '-') { 21 | isNegative = true; 22 | num1 = num1.substring(1); 23 | } 24 | 25 | if (num2.charAt(0) == '-') { 26 | if (isNegative) { 27 | isNegative = false; 28 | } else { 29 | isNegative = true; 30 | } 31 | num2 = num2.substring(1); 32 | } 33 | 34 | int m = num1.length(); 35 | int n = num2.length(); 36 | 37 | int[] result = new int[m + n]; 38 | for (int i = n - 1; i >= 0; i--) { 39 | int carry = 0; 40 | int position = m + i; 41 | for (int j = m - 1; j >= 0; j--) { 42 | int product = result[position] + carry + ((num2.charAt(i) - '0') * (num1.charAt(j) - '0')); 43 | result[position] = product % 10; 44 | carry = product / 10; 45 | position--; 46 | } 47 | result[position] = carry; 48 | } 49 | 50 | boolean leadingZeros = true; 51 | StringBuilder product = new StringBuilder(isNegative ? "-" : ""); 52 | for (int i : result) { 53 | if (i > 0) { 54 | leadingZeros = false; 55 | } 56 | 57 | if (!leadingZeros) { 58 | product.append(i); 59 | } 60 | } 61 | 62 | return product.length() == 0 ? "0" : product.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ###################### 2 | # Project Specific 3 | ###################### 4 | /src/main/webapp/content/css/main.css 5 | /target/www/** 6 | /src/test/javascript/coverage/ 7 | /src/test/javascript/PhantomJS*/ 8 | 9 | ###################### 10 | # Node 11 | ###################### 12 | /node/ 13 | node_tmp/ 14 | node_modules/ 15 | npm-debug.log.* 16 | 17 | ###################### 18 | # SASS 19 | ###################### 20 | .sass-cache/ 21 | 22 | ###################### 23 | # Eclipse 24 | ###################### 25 | *.pydevproject 26 | .project 27 | .metadata 28 | tmp/ 29 | tmp/**/* 30 | *.tmp 31 | *.bak 32 | *.swp 33 | *~.nib 34 | local.properties 35 | .classpath 36 | .settings/ 37 | .loadpath 38 | .factorypath 39 | /src/main/resources/rebel.xml 40 | 41 | # External tool builders 42 | .externalToolBuilders/** 43 | 44 | # Locally stored "Eclipse launch configurations" 45 | *.launch 46 | 47 | # CDT-specific 48 | .cproject 49 | 50 | # PDT-specific 51 | .buildpath 52 | 53 | ###################### 54 | # Intellij 55 | ###################### 56 | .idea/ 57 | *.iml 58 | *.iws 59 | *.ipr 60 | *.ids 61 | *.orig 62 | 63 | ###################### 64 | # Visual Studio Code 65 | ###################### 66 | .vscode/ 67 | 68 | ###################### 69 | # Maven 70 | ###################### 71 | /log/ 72 | /target/ 73 | 74 | ###################### 75 | # Gradle 76 | ###################### 77 | .gradle/ 78 | /build/ 79 | 80 | ###################### 81 | # Package Files 82 | ###################### 83 | *.jar 84 | *.war 85 | *.ear 86 | *.db 87 | 88 | ###################### 89 | # Windows 90 | ###################### 91 | # Windows image file caches 92 | Thumbs.db 93 | 94 | # Folder config file 95 | Desktop.ini 96 | 97 | ###################### 98 | # Mac OSX 99 | ###################### 100 | .DS_Store 101 | .svn 102 | 103 | # Thumbnails 104 | ._* 105 | 106 | # Files that might appear on external disk 107 | .Spotlight-V100 108 | .Trashes 109 | 110 | ###################### 111 | # Directories 112 | ###################### 113 | /bin/ 114 | /out/ 115 | /deploy/ 116 | 117 | ###################### 118 | # Logs 119 | ###################### 120 | *.log 121 | 122 | ###################### 123 | # Others 124 | ###################### 125 | *.class 126 | *.*~ 127 | *~ 128 | .merge_file* 129 | 130 | ###################### 131 | # Gradle Wrapper 132 | ###################### 133 | !gradle/wrapper/gradle-wrapper.jar 134 | 135 | ###################### 136 | # Maven Wrapper 137 | ###################### 138 | !.mvn/wrapper/maven-wrapper.jar 139 | 140 | ###################### 141 | # ESLint 142 | ###################### 143 | .eslintcache -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/AddTwoNumbersInLinkedListForm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | public class AddTwoNumbersInLinkedListForm { 4 | 5 | public static void main(String[] args) { 6 | // Test 7 | ListNode l1 = new ListNode(2).next(new ListNode(4).next(new ListNode(6))); 8 | ListNode l2 = new ListNode(5).next(new ListNode(6).next(new ListNode(4))); 9 | 10 | System.out.println(l1); 11 | System.out.println(l2); 12 | System.out.println(addTwoNumbers(l1, l2)); 13 | 14 | // Test 15 | l1 = new ListNode(5); 16 | l2 = new ListNode(5); 17 | 18 | System.out.println(l1); 19 | System.out.println(l2); 20 | System.out.println(addTwoNumbers(l1, l2)); 21 | 22 | // Test 23 | l1 = new ListNode(1).next(new ListNode(8)); 24 | l2 = new ListNode(0); 25 | 26 | System.out.println(l1); 27 | System.out.println(l2); 28 | System.out.println(addTwoNumbers(l1, l2)); 29 | 30 | // Test 31 | l1 = new ListNode(0); 32 | l2 = new ListNode(1).next(new ListNode(8)); 33 | 34 | System.out.println(l1); 35 | System.out.println(l2); 36 | System.out.println(addTwoNumbers(l1, l2)); 37 | } 38 | 39 | public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { 40 | int carry = 0; 41 | ListNode head = null; 42 | ListNode previous = null; 43 | while (l1 != null || l2 != null) { 44 | int sum = carry; 45 | if (l1 != null) { 46 | sum += l1.val; 47 | l1 = l1.next; 48 | } 49 | 50 | if (l2 != null) { 51 | sum += l2.val; 52 | l2 = l2.next; 53 | } 54 | 55 | carry = sum / 10; 56 | 57 | ListNode node = new ListNode(sum % 10); 58 | if (head == null) { 59 | head = node; 60 | } else { 61 | previous.next = node; 62 | } 63 | 64 | previous = node; 65 | } 66 | 67 | if (carry != 0) { 68 | previous.next = new ListNode(carry); 69 | } 70 | 71 | return head; 72 | } 73 | 74 | private static class ListNode { 75 | int val; 76 | ListNode next; 77 | 78 | ListNode(int x) { 79 | val = x; 80 | } 81 | 82 | public ListNode next(ListNode next) { 83 | this.next = next; 84 | return this; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return val + "->" + next; 90 | } 91 | } 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/OverloadingOverridingExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * See complete articles on below links 7 | * 8 | * https://www.programmingmitra.com/2017/05/everything-about-method-overloading-vs-method-overriding.html, 9 | * https://www.programmingmitra.com/2017/12/why-we-should-follow-method-overriding-rules.html, 10 | * https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html, 11 | * https://www.programmingmitra.com/2018/11/why-instance-variable-of-super-class-is-not-overridden-In-sub-class.html 12 | */ 13 | public class OverloadingOverridingExample { 14 | 15 | public static void main(String[] args) { 16 | 17 | Mammal mammal1 = new Cat(); 18 | System.out.println(mammal1.speak()); 19 | 20 | Mammal mammal2 = new Human(); 21 | System.out.println(mammal2.speak()); 22 | 23 | // Compilation error speak(String) is specific to Human class and we can not refer it from Mammal reference 24 | // mammal1.speak("Hindi"); 25 | 26 | Human human = new Human(); 27 | System.out.println(human.speak()); 28 | System.out.println(human.speak("Hindi")); 29 | 30 | // Compilation Error ambiguous method call between calculate(int, long) and calculate(long, int) 31 | // human.calculate(5, 5); 32 | 33 | 34 | System.out.println(human.calculate(5, 5L)); 35 | System.out.println(human.calculate(5L, 5)); 36 | } 37 | 38 | static abstract class Mammal { 39 | public String speak() { 40 | return "Well might speak something like ohlllalalalalalaoaoaoa"; 41 | } 42 | } 43 | 44 | static class Cat extends Mammal { 45 | 46 | @Override 47 | public String speak() { 48 | return "Meow"; 49 | } 50 | 51 | } 52 | 53 | static class Human extends Mammal { 54 | 55 | @Override 56 | // Using Override annotation is not necessary but using it will tell you if you are not obeying overriding rules 57 | public String speak() { 58 | return "Hello"; 59 | } 60 | 61 | // Valid overload of speak 62 | public String speak(String language) { 63 | if (language.equals("Hindi")) return "Namaste"; 64 | else return "Hello"; 65 | } 66 | 67 | public long calculate(int a, long b) { 68 | return a + b; 69 | } 70 | 71 | // However nobody should do it but Valid overload of calculate by just changing sequence of arguments 72 | public long calculate(long b, int a) { 73 | return a + b; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/VariableShadowingExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * Why Instance Variable Of Super Class Is Not Overridden In Sub Class 7 | * 8 | * See complete articles on below links 9 | * 10 | * https://www.programmingmitra.com/2018/11/why-instance-variable-of-super-class-is-not-overridden-In-sub-class.html, 11 | * https://www.programmingmitra.com/2017/05/everything-about-method-overloading-vs-method-overriding.html, 12 | * https://www.programmingmitra.com/2017/12/why-we-should-follow-method-overriding-rules.html, 13 | * https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html, 14 | */ 15 | public class VariableShadowingExample { 16 | public static void main(String[] args) { 17 | Parent parent1 = new Parent(); 18 | parent1.printInstanceVar(); // Output - "Parent`s Instance Variable" 19 | System.out.println(parent1.x); // Output - "Parent`s Instance Variable" 20 | 21 | Child child = new Child(); 22 | child.printInstanceVar();// Output - "Child`s Instance Variable, Parent`s Instance Variable" 23 | System.out.println(child.x);// Output - "Child`s Instance Variable" 24 | 25 | Parent parent2 = new Child(); 26 | parent2.printInstanceVar();// Output - "Child`s Instance Variable, Parent`s Instance Variable" 27 | System.out.println(parent2.x);// Output - Parent`s Instance Variable 28 | 29 | // Accessing child's variable from parent's reference by type casting 30 | System.out.println(((Child) parent2).x);// Output - "Child`s Instance Variable" 31 | } 32 | 33 | static class Parent { 34 | // Declaring instance variable by name `x` 35 | String x = "Parent`s Instance Variable"; 36 | 37 | public void printInstanceVar() { 38 | System.out.println(x); 39 | } 40 | 41 | public void printLocalVar() { 42 | // Shadowing instance variable `x` by a local variable with same name 43 | String x = "Local Variable"; 44 | System.out.println(x); 45 | 46 | // If we still want to access instance variable, we do that by using `this.x` 47 | System.out.println(this.x); 48 | } 49 | } 50 | 51 | static class Child extends Parent { 52 | 53 | // Hiding Parent class's variable `x` by defining a variable in child class with same name. 54 | String x = "Child`s Instance Variable"; 55 | 56 | @Override 57 | public void printInstanceVar() { 58 | System.out.print(x); 59 | 60 | // If we still want to access variable from super class, we do that by using `super.x` 61 | System.out.print(", " + super.x + "\n"); 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/PrimsAlgorithm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.Arrays; 4 | 5 | // Using adjacency matrix 6 | public class PrimsAlgorithm { 7 | public static void main(String[] args) { 8 | 9 | Graph graph = new Graph(6); 10 | graph.addEdge(0, 1, 4); 11 | graph.addEdge(0, 2, 7); 12 | graph.addEdge(1, 2, 8); 13 | graph.addEdge(1, 3, 13); 14 | graph.addEdge(1, 4, 11); 15 | graph.addEdge(2, 3, 12); 16 | graph.addEdge(2, 4, 10); 17 | graph.addEdge(3, 4, 9); 18 | graph.addEdge(3, 5, 15); 19 | graph.addEdge(4, 5, 14); 20 | 21 | int[] mst = findMST(graph); 22 | System.out.println(Arrays.toString(mst)); 23 | for (int i = 1; i < mst.length; i++) { 24 | System.out.printf("Edge %d -> %d with weight=%d%n", mst[i], i, graph.weight(mst[i], i)); 25 | } 26 | } 27 | 28 | public static int[] findMST(Graph graph) { 29 | int[] currentCosts = new int[graph.V]; 30 | int[] MST = new int[graph.V]; 31 | int[] inMST = new int[graph.V]; 32 | 33 | for (int i = 0; i < graph.V; i++) { 34 | currentCosts[i] = Integer.MAX_VALUE; 35 | inMST[i] = 0; 36 | } 37 | 38 | currentCosts[0] = 0; 39 | MST[0] = -1; 40 | 41 | for (int i = 0; i < graph.V; i++) { 42 | int x = findMinCostCrossingVertex(currentCosts, inMST); 43 | inMST[x] = 1; 44 | for (int y = 0; y < graph.V; y++) { 45 | int weight = graph.weight(x, y); 46 | if (inMST[y] == 0 && weight != 0 && weight < currentCosts[y]) { 47 | currentCosts[y] = weight; 48 | MST[y] = x; 49 | } 50 | } 51 | } 52 | 53 | return MST; 54 | } 55 | 56 | private static int findMinCostCrossingVertex(int[] currentCosts, int[] inMST) { 57 | int minCost = Integer.MAX_VALUE; 58 | int minCostVertex = Integer.MAX_VALUE; 59 | for (int v = 0; v < currentCosts.length; v++) { 60 | if (inMST[v] == 0 && currentCosts[v] < minCost) { 61 | minCost = currentCosts[v]; 62 | minCostVertex = v; 63 | } 64 | } 65 | return minCostVertex; 66 | } 67 | 68 | 69 | private static class Graph { 70 | int V, E = 0; 71 | int[][] adjMatrix; 72 | 73 | public Graph(int V) { 74 | this.V = V; 75 | adjMatrix = new int[V][V]; 76 | } 77 | 78 | public int weight(int from, int to) { 79 | return adjMatrix[from][to] != 0 ? adjMatrix[from][to] : adjMatrix[to][from]; 80 | } 81 | 82 | public void addEdge(int from, int to, int weight) { 83 | E++; 84 | adjMatrix[from][to] = weight; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/ImmutableClassExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | /** 8 | * @author Naresh Joshi 9 | * 10 | * See complete articles on below links 11 | * 12 | * https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html, 13 | * https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html 14 | */ 15 | public class ImmutableClassExample { 16 | 17 | public static void main(String[] args) throws ParseException { 18 | Date dob = new SimpleDateFormat("dd-mm-yyyy").parse("10-12-1993"); 19 | ImmutableEmployee employee = new ImmutableEmployee(1, "Naresh", dob); 20 | 21 | System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993} 22 | 23 | dob.setMonth(1); 24 | System.out.println(dob); // Prints - Wed Feb 10 00:12:00 IST 1993 25 | 26 | Date temp = employee.getDob(); 27 | temp.setMonth(2); 28 | System.out.println(temp); // Prints - Wed Mar 10 00:12:00 IST 1993 29 | 30 | System.out.println(employee.getDob()); // Prints - Sun Jan 10 00:12:00 IST 1993 31 | System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993} 32 | } 33 | } 34 | 35 | // 1. Declare your class as final, So other classes can't extend it and break its immutability 36 | final class ImmutableEmployee { 37 | 38 | // 2. Make all your fields private they can't be accessed outside your class 39 | // 3. Mark them as final so no one can modify them anywhere else apart from the constructor, if you do not have any specific requirement to not do so 40 | private final int id; 41 | private final String name; 42 | private final Date dob; 43 | 44 | // 4. Create an constructor with argument so you can assign instantiate your object with a proper state 45 | public ImmutableEmployee(int id, String name, Date dob) { 46 | this.id = id; 47 | this.name = name; 48 | // 5. Initialise all your fields by deeply copying them if they are not immutable in nature 49 | this.dob = new Date(dob.getTime()); 50 | } 51 | 52 | // 6. Do not provide setters for your fields, or define them private if you have some requirement 53 | public int getId() { 54 | return id; 55 | } 56 | 57 | public String getName() { 58 | return name; 59 | } 60 | 61 | // 7. Instead of returning objects from the getters return deep copy them if your objects are not immutable 62 | public Date getDob() { 63 | return new Date(dob.getTime()); 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return "ImmutableEmployee{" + 69 | "id=" + id + 70 | ", name='" + name + '\'' + 71 | ", dob=" + dob + 72 | '}'; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/KruskalsAlgoWithParentDS.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.Arrays; 4 | 5 | public class KruskalsAlgoWithParentDS { 6 | public static void main(String[] args) { 7 | Graph graph = new Graph(6, 10); 8 | graph.addEdge(0, 1, 4); 9 | graph.addEdge(0, 2, 7); 10 | graph.addEdge(1, 2, 8); 11 | graph.addEdge(1, 3, 13); 12 | graph.addEdge(1, 4, 11); 13 | graph.addEdge(2, 3, 12); 14 | graph.addEdge(2, 4, 10); 15 | graph.addEdge(3, 4, 9); 16 | graph.addEdge(3, 5, 15); 17 | graph.addEdge(4, 5, 14); 18 | 19 | Graph MST = findMST(graph); 20 | Edge[] edges = MST.edges; 21 | 22 | System.out.println("Number of edge for minimum spanning is=" + edges.length); 23 | for (int i = 0; i < edges.length; i++) { 24 | System.out.println(edges[i]); 25 | } 26 | } 27 | 28 | 29 | private static Graph findMST(Graph graph) { 30 | Edge[] edges = graph.edges; 31 | Arrays.sort(edges); 32 | 33 | int[] parent = new int[graph.V]; 34 | for (int i = 0; i < parent.length; i++) { 35 | parent[i] = i; 36 | } 37 | 38 | int counter = 0; 39 | Edge[] mstEdges = new Edge[graph.V - 1]; 40 | for (int i = 0; i < graph.E; i++) { 41 | Edge edge = edges[i]; 42 | 43 | int x = find(edge.from, parent); 44 | int y = find(edge.to, parent); 45 | if (x != y) { 46 | mstEdges[counter++] = edge; 47 | union(x, y, parent); 48 | } 49 | } 50 | 51 | return new Graph(graph.V, mstEdges); 52 | } 53 | 54 | private static void union(int x, int y, int[] parent) { 55 | if (x < y) 56 | parent[y] = x; 57 | else 58 | parent[x] = y; 59 | } 60 | 61 | private static int find(int x, int[] parent) { 62 | int temp = x; 63 | while (temp != parent[temp]) 64 | temp = parent[temp]; 65 | return temp; 66 | } 67 | 68 | private static class Graph { 69 | public int V, E; 70 | public Edge[] edges; 71 | 72 | public int size = 0; 73 | 74 | public Graph(int V, int E) { 75 | this.V = V; 76 | this.E = E; 77 | this.edges = new Edge[E]; 78 | } 79 | 80 | public Graph(int V, Edge[] edges) { 81 | this.V = V; 82 | this.edges = edges; 83 | this.E = edges.length; 84 | } 85 | 86 | public void addEdge(int from, int to, int weight) { 87 | edges[size++] = new Edge(from, to, weight); 88 | } 89 | } 90 | 91 | private static class Edge implements Comparable { 92 | public int from, to, weight; 93 | 94 | public Edge(int from, int to, int weight) { 95 | this.from = from; 96 | this.to = to; 97 | this.weight = weight; 98 | } 99 | 100 | @Override 101 | public int compareTo(Edge o) { 102 | return Integer.compare(this.weight, o.weight); 103 | } 104 | 105 | @Override 106 | public String toString() { 107 | return String.format("Edge %d -> %d with weight=%d", from, to, weight); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/KruskalsAlgoWithNameDS.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.Arrays; 4 | 5 | public class KruskalsAlgoWithNameDS { 6 | public static void main(String[] args) { 7 | Graph graph = new Graph(6, 10); 8 | graph.addEdge(0, 1, 4); 9 | graph.addEdge(0, 2, 7); 10 | graph.addEdge(1, 2, 8); 11 | graph.addEdge(1, 3, 13); 12 | graph.addEdge(1, 4, 11); 13 | graph.addEdge(2, 3, 12); 14 | graph.addEdge(2, 4, 10); 15 | graph.addEdge(3, 4, 9); 16 | graph.addEdge(3, 5, 15); 17 | graph.addEdge(4, 5, 14); 18 | 19 | Graph MST = findMST(graph); 20 | Edge[] edges = MST.edges; 21 | 22 | System.out.println("Number of edge for minimum spanning is=" + edges.length); 23 | for (int i = 0; i < edges.length; i++) { 24 | System.out.println(edges[i]); 25 | } 26 | } 27 | 28 | 29 | private static Graph findMST(Graph graph) { 30 | Edge[] edges = graph.edges; 31 | Arrays.sort(edges); 32 | 33 | int[] name = new int[graph.V]; 34 | for (int i = 0; i < name.length; i++) { 35 | name[i] = i; 36 | } 37 | 38 | int counter = 0; 39 | Edge[] mstEdges = new Edge[graph.V - 1]; 40 | for (int i = 0; i < graph.E; i++) { 41 | Edge edge = edges[i]; 42 | 43 | int x = find(edge.from, name); 44 | int y = find(edge.to, name); 45 | if (x != y) { 46 | mstEdges[counter++] = edge; 47 | union(x, y, name); 48 | } 49 | } 50 | 51 | return new Graph(graph.V, mstEdges); 52 | } 53 | 54 | private static void union(int x, int y, int[] name) { 55 | if (x < y) { 56 | for (int i = 0; i < name.length; i++) { 57 | if (name[i] == y) 58 | name[i] = x; 59 | } 60 | } else { 61 | for (int i = 0; i < name.length; i++) { 62 | if (name[i] == x) 63 | name[i] = y; 64 | } 65 | } 66 | } 67 | 68 | private static int find(int x, int[] name) { 69 | return name[x]; 70 | } 71 | 72 | private static class Graph { 73 | public int V, E; 74 | public Edge[] edges; 75 | 76 | public int size = 0; 77 | 78 | public Graph(int V, int E) { 79 | this.V = V; 80 | this.E = E; 81 | this.edges = new Edge[E]; 82 | } 83 | 84 | public Graph(int V, Edge[] edges) { 85 | this.V = V; 86 | this.edges = edges; 87 | this.E = edges.length; 88 | } 89 | 90 | public void addEdge(int from, int to, int weight) { 91 | edges[size++] = new Edge(from, to, weight); 92 | } 93 | } 94 | 95 | private static class Edge implements Comparable { 96 | public int from, to, weight; 97 | 98 | public Edge(int from, int to, int weight) { 99 | this.from = from; 100 | this.to = to; 101 | this.weight = weight; 102 | } 103 | 104 | @Override 105 | public int compareTo(Edge o) { 106 | return Integer.compare(this.weight, o.weight); 107 | } 108 | 109 | @Override 110 | public String toString() { 111 | return String.format("Edge %d -> %d with weight=%d", from, to, weight); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/ObjectCreation.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | import java.io.Serializable; 8 | import java.lang.reflect.Constructor; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @author Naresh Joshi 13 | * 14 | * See complete articles on below links. 15 | * 16 | * https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html, 17 | * https://www.programmingmitra.com/2016/05/creating-objects-through-reflection-in-java-with-example.html 18 | */ 19 | public class ObjectCreation { 20 | public static void main(String... args) throws Exception { 21 | 22 | // 1. By using new keyword 23 | Employee emp1 = new Employee(); 24 | emp1.setName("emp1"); 25 | 26 | 27 | // 2. By using Class class's newInstance() method 28 | // Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance(); 29 | Employee emp2 = Employee.class.newInstance(); 30 | emp2.setName("emp2"); 31 | 32 | 33 | // 3. By using Constructor class's newInstance() method 34 | Constructor constructor = Employee.class.getConstructor(); 35 | 36 | Employee emp3 = constructor.newInstance(); 37 | emp3.setName("emp3"); 38 | 39 | // 4. By using clone() method 40 | Employee emp4 = (Employee) emp3.clone(); 41 | emp4.setName("emp4"); 42 | 43 | 44 | // 5. By using Deserialization 45 | 46 | // Serialization 47 | try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"))) { 48 | out.writeObject(emp4); 49 | } 50 | 51 | //Deserialization 52 | Employee emp5; 53 | try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"))) { 54 | emp5 = (Employee) in.readObject(); 55 | emp5.setName("emp5"); 56 | } 57 | 58 | System.out.println(emp1 + ", hashcode : " + emp1.hashCode()); 59 | System.out.println(emp2 + ", hashcode : " + emp2.hashCode()); 60 | System.out.println(emp3 + ", hashcode : " + emp3.hashCode()); 61 | System.out.println(emp4 + ", hashcode : " + emp4.hashCode()); 62 | System.out.println(emp5 + ", hashcode : " + emp5.hashCode()); 63 | } 64 | } 65 | 66 | class Employee implements Cloneable, Serializable { 67 | 68 | private static final long serialVersionUID = 1L; 69 | 70 | private String name; 71 | 72 | public Employee() { 73 | System.out.println("Employee Constructor Called..."); 74 | } 75 | 76 | public String getName() { 77 | return name; 78 | } 79 | 80 | public void setName(String name) { 81 | this.name = name; 82 | } 83 | 84 | @Override 85 | public boolean equals(Object o) { 86 | if (this == o) return true; 87 | if (o == null || getClass() != o.getClass()) return false; 88 | Employee employee = (Employee) o; 89 | return Objects.equals(name, employee.name); 90 | } 91 | 92 | @Override 93 | public int hashCode() { 94 | return Objects.hash(name); 95 | } 96 | 97 | @Override 98 | public String toString() { 99 | return String.format("Employee{name='%s'}", name); 100 | } 101 | 102 | @Override 103 | public Object clone() { 104 | 105 | Object obj = null; 106 | try { 107 | obj = super.clone(); 108 | } catch (CloneNotSupportedException e) { 109 | e.printStackTrace(); 110 | } 111 | return obj; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/KruskalsAlgoWithParentDSAndSizeAndPathCompression.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | 6 | public class KruskalsAlgoWithParentDSAndSizeAndPathCompression { 7 | public static void main(String[] args) { 8 | Graph graph = new Graph(6, 10); 9 | graph.addEdge(0, 1, 4); 10 | graph.addEdge(0, 2, 7); 11 | graph.addEdge(1, 2, 8); 12 | graph.addEdge(1, 3, 13); 13 | graph.addEdge(1, 4, 11); 14 | graph.addEdge(2, 3, 12); 15 | graph.addEdge(2, 4, 10); 16 | graph.addEdge(3, 4, 9); 17 | graph.addEdge(3, 5, 15); 18 | graph.addEdge(4, 5, 14); 19 | 20 | Graph MST = findMST(graph); 21 | Edge[] edges = MST.edges; 22 | 23 | System.out.println("Number of edge for minimum spanning is=" + edges.length); 24 | for (int i = 0; i < edges.length; i++) { 25 | System.out.println(edges[i]); 26 | } 27 | } 28 | 29 | private static Graph findMST(Graph graph) { 30 | Edge[] edges = graph.edges; 31 | Arrays.sort(edges); 32 | 33 | int[] parent = new int[graph.V]; 34 | int[] size = new int[graph.V]; 35 | for (int i = 0; i < graph.V; i++) { 36 | parent[i] = i; 37 | size[i] = 1; 38 | } 39 | 40 | int counter = 0; 41 | Edge[] mstEdges = new Edge[graph.V - 1]; 42 | for (int i = 0; i < graph.E; i++) { 43 | Edge edge = edges[i]; 44 | 45 | int x = find(edge.from, parent); 46 | int y = find(edge.to, parent); 47 | if (x != y) { 48 | mstEdges[counter++] = edge; 49 | union(x, y, parent, size); 50 | } 51 | } 52 | 53 | return new Graph(graph.V, mstEdges); 54 | } 55 | 56 | private static void union(int x, int y, int[] parent, int[] size) { 57 | // Merging smaller sized tree into larger size tree 58 | // Summing up size of bigger tree by smaller tree 59 | // Marking size of smaller sized tree 0 60 | if (size[x] <= size[y]) { 61 | parent[x] = y; 62 | size[y] = size[y] + size[x]; 63 | size[x] = 0; 64 | } else { 65 | parent[y] = x; 66 | size[x] = size[x] + size[y]; 67 | size[y] = 0; 68 | } 69 | } 70 | 71 | private static int find(int x, int[] parent) { 72 | int temp = x; 73 | LinkedList list = new LinkedList<>(); 74 | while (temp != parent[temp]) { 75 | temp = parent[temp]; 76 | list.add(temp); 77 | } 78 | 79 | // Flattening the tree, x1->x2->x3->x4->r will become x1->r,x2->r,x3->r,x4->r 80 | while (list.size() > 0) { 81 | Integer node = list.remove(); 82 | parent[node] = temp; 83 | } 84 | return temp; 85 | } 86 | 87 | private static class Graph { 88 | public int V, E; 89 | public Edge[] edges; 90 | 91 | public int size = 0; 92 | 93 | public Graph(int V, int E) { 94 | this.V = V; 95 | this.E = E; 96 | this.edges = new Edge[E]; 97 | } 98 | 99 | public Graph(int V, Edge[] edges) { 100 | this.V = V; 101 | this.edges = edges; 102 | this.E = edges.length; 103 | } 104 | 105 | public void addEdge(int from, int to, int weight) { 106 | edges[size++] = new Edge(from, to, weight); 107 | } 108 | } 109 | 110 | private static class Edge implements Comparable { 111 | public int from, to, weight; 112 | 113 | public Edge(int from, int to, int weight) { 114 | this.from = from; 115 | this.to = to; 116 | this.weight = weight; 117 | } 118 | 119 | @Override 120 | public int compareTo(Edge o) { 121 | return Integer.compare(this.weight, o.weight); 122 | } 123 | 124 | @Override 125 | public String toString() { 126 | return String.format("Edge %d -> %d with weight=%d", from, to, weight); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/PrimsAlgorithmWithHeap.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | // Using adjacency matrix 6 | public class PrimsAlgorithmWithHeap { 7 | public static void main(String[] args) { 8 | 9 | Graph graph = new Graph(6); 10 | graph.addEdge(0, 1, 4); 11 | graph.addEdge(0, 2, 7); 12 | graph.addEdge(1, 2, 8); 13 | graph.addEdge(1, 3, 13); 14 | graph.addEdge(1, 4, 11); 15 | graph.addEdge(2, 3, 12); 16 | graph.addEdge(2, 4, 10); 17 | graph.addEdge(3, 4, 9); 18 | graph.addEdge(3, 5, 15); 19 | graph.addEdge(4, 5, 14); 20 | 21 | System.out.println("For below tree:"); 22 | System.out.println( 23 | " /0\\\n" + 24 | " / \\ \n" + 25 | " 4/ \\7\n" + 26 | " / 8 \\\n" + 27 | " 1 ------- 2\n" + 28 | " | \\11 12/|\n" + 29 | " 13| \\ / | 10\n" + 30 | " | / \\ |\n" + 31 | " | / \\ |\n" + 32 | " | / \\ |\n" + 33 | " 3 ------- 4\n" + 34 | " \\ 9 /\n" + 35 | " 15\\ /14\n" + 36 | " \\ /\n" + 37 | " \\5/" 38 | ); 39 | 40 | Edge[] mstEdges = findMST(graph); 41 | 42 | System.out.println("Minimum spanning tree generated through PrimsAlgo contains edges:"); 43 | for (int i = 0; i < mstEdges.length; i++) { 44 | System.out.println(mstEdges[i]); 45 | } 46 | 47 | } 48 | 49 | public static Edge[] findMST(Graph graph) { 50 | Edge[] MST = new Edge[graph.V - 1]; 51 | int[] inMST = new int[graph.V]; 52 | PriorityQueue minHeap = new PriorityQueue<>(graph.E); 53 | 54 | inMST[0] = 1; 55 | 56 | for (int v = 1; v < graph.V; v++) { 57 | int weight = graph.weight(0, v); 58 | if (weight != 0) { 59 | minHeap.add(new Edge(0, v, weight)); 60 | } 61 | } 62 | 63 | int count = 0; 64 | while (count < graph.V - 1) { 65 | Edge edge = minHeap.remove(); 66 | int x = edge.from; 67 | int y = edge.to; 68 | 69 | if (inMST[x] == 1 && inMST[y] == 0) { 70 | inMST[y] = 1; 71 | MST[count++] = edge; 72 | for (int z = 0; z < graph.V; z++) { 73 | int weight = graph.weight(y, z); 74 | if (inMST[z] == 0 && weight != 0) { 75 | minHeap.add(new Edge(y, z, weight)); 76 | } 77 | } 78 | } 79 | } 80 | 81 | return MST; 82 | } 83 | 84 | private static class Graph { 85 | int V, E = 0; 86 | int[][] adjMatrix; 87 | 88 | public Graph(int V) { 89 | this.V = V; 90 | adjMatrix = new int[V][V]; 91 | } 92 | 93 | public int weight(int from, int to) { 94 | return adjMatrix[from][to] != 0 ? adjMatrix[from][to] : adjMatrix[to][from]; 95 | } 96 | 97 | public void addEdge(int from, int to, int weight) { 98 | E++; 99 | adjMatrix[from][to] = weight; 100 | } 101 | } 102 | 103 | private static class Edge implements Comparable { 104 | public int from, to, weight; 105 | 106 | public Edge(int from, int to, int weight) { 107 | this.from = from; 108 | this.to = to; 109 | this.weight = weight; 110 | } 111 | 112 | @Override 113 | public int compareTo(Edge o) { 114 | return Integer.compare(this.weight, o.weight); 115 | } 116 | 117 | @Override 118 | public String toString() { 119 | return String.format("%d -> %d with weight=%d", from, to, weight); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/apsp/FloydWarshallAlgorithm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.apsp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Floyd-Warshall all pair shortest path (apsp) algorithm for directed graph, 8 | * It works only on positive weight edges, 9 | * It is based on dynamic programming. 10 | *

11 | * Time complexity = O(E.logV), In worst case E = V^2, Which wor case time complexity = O(V^2.logV) 12 | * Space complexity = O(E+V) 13 | * 14 | * @author Naresh Joshi 15 | */ 16 | /* 17 | Algorithm :- 18 | 19 | dist = |V| × |V| array of minimum distances initialized to ∞ (infinity) 20 | for each vertex v do 21 | dist[v][v] = 0 22 | for each edge (u, v) do 23 | dist[u][v] = w(u, v) // The weight of the edge (u, v) 24 | 25 | for k from 1 to |V| 26 | for i from 1 to |V| 27 | for j from 1 to |V| 28 | if dist[i][j] > dist[i][k] + dist[k][j] 29 | dist[i][j] = dist[i][k] + dist[k][j] 30 | end if 31 | */ 32 | public class FloydWarshallAlgorithm { 33 | 34 | private static final int INFINITY = 999999; 35 | 36 | private static int[][] runFloydWarshall(Graph graph) { 37 | int[][] dist = new int[graph.V][graph.V]; 38 | for (int i = 0; i < graph.V; i++) { 39 | dist[i][i] = 0; 40 | for (int j = 0; j < graph.V; j++) { 41 | dist[i][j] = INFINITY; 42 | } 43 | } 44 | 45 | for (Edge edge : graph.edges) { 46 | dist[edge.from][edge.to] = edge.weight; 47 | } 48 | 49 | for (int k = 0; k < graph.V; k++) { 50 | for (int i = 0; i < graph.V; i++) { 51 | for (int j = 0; j < graph.V; j++) { 52 | if (dist[i][j] > dist[i][k] + dist[k][j]) 53 | dist[i][j] = dist[i][k] + dist[k][j]; 54 | } 55 | } 56 | } 57 | 58 | return dist; 59 | } 60 | 61 | public static void main(String[] args) { 62 | Graph graph = new Graph(6); 63 | graph.addEdge(0, 1, 4); 64 | graph.addEdge(0, 2, 7); 65 | graph.addEdge(1, 2, 8); 66 | graph.addEdge(1, 3, 13); 67 | graph.addEdge(1, 4, 11); 68 | graph.addEdge(2, 3, 12); 69 | graph.addEdge(2, 4, 10); 70 | graph.addEdge(3, 4, 9); 71 | graph.addEdge(3, 5, 15); 72 | graph.addEdge(4, 5, 14); 73 | 74 | System.out.println("For below tree:"); 75 | System.out.println( 76 | " /0\\\n" + 77 | " / \\ \n" + 78 | " 4/ \\7\n" + 79 | " / 8 \\\n" + 80 | " 1 ------- 2\n" + 81 | " | \\11 12/|\n" + 82 | " 13| \\ / | 10\n" + 83 | " | / \\ |\n" + 84 | " | / \\ |\n" + 85 | " | / \\ |\n" + 86 | " 3 ------- 4\n" + 87 | " \\ 9 /\n" + 88 | " 15\\ /14\n" + 89 | " \\ /\n" + 90 | " \\5/" 91 | ); 92 | 93 | int[][] dist = runFloydWarshall(graph); 94 | 95 | System.out.println("All pair shortest distances generated by FloydWarshallAlgorithm are:"); 96 | for (int i = 0; i < graph.V; i++) { 97 | for (int j = 0; j < graph.V; j++) { 98 | if (dist[i][j] != INFINITY) 99 | System.out.println(String.format("Distance of path %d --> %d is %d", i, j, dist[i][j])); 100 | } 101 | } 102 | } 103 | 104 | private static class Graph { 105 | public int V, E; 106 | public List edges; 107 | 108 | public Graph(int V) { 109 | this.V = V; 110 | this.edges = new ArrayList<>(); 111 | } 112 | 113 | public void addEdge(int from, int to, int weight) { 114 | edges.add(new Edge(from, to, weight)); 115 | E++; 116 | } 117 | } 118 | 119 | private static class Edge { 120 | public int from, to, weight; 121 | 122 | public Edge(int from, int to, int weight) { 123 | this.from = from; 124 | this.to = to; 125 | this.weight = weight; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/CopyConstructorExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | /** 4 | * @author Naresh Joshi 5 | * 6 | * See complete article on below link 7 | * 8 | * https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html, 9 | * https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html, 10 | * https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html 11 | */ 12 | public class CopyConstructorExample { 13 | 14 | public static void main(String[] args) { 15 | Mammal mammal = new Mammal("Human"); 16 | Human human = new Human("Human", "Naresh"); 17 | 18 | Mammal mammalHuman = new Human("Human", "Mahesh"); 19 | 20 | Mammal clonedMammal = new Mammal(mammal); 21 | //Mammal clonedMammal = mammal.cloneObject(); 22 | 23 | Human clonedHuman = new Human(human); 24 | //Human clonedHuman = human.cloneObject(); 25 | 26 | //Mammal clonedMammalHuman = new Human(mammalHuman); // compilation error 27 | //Mammal clonedMammalHuman = new Mammal(mammalHuman); 28 | Mammal clonedMammalHuman = mammalHuman.cloneObject(); 29 | 30 | System.out.println("Object " + mammal + " and copied object " + clonedMammal + " are == : " + (mammal == clonedMammal)); 31 | System.out.println("Object " + mammal + " and copied object " + clonedMammal + " are equal : " + (mammal.equals(clonedMammal)) + "\n"); 32 | 33 | 34 | System.out.println("Object " + human + " and copied object " + clonedHuman + " are == : " + (human == clonedHuman)); 35 | System.out.println("Object " + human + " and copied object " + clonedHuman + " are equal : " + (human.equals(clonedHuman)) + "\n"); 36 | 37 | System.out.println("Object " + mammalHuman + " and copied object " + clonedMammalHuman + " are == : " + (mammalHuman == clonedMammalHuman)); 38 | System.out.println("Object " + mammalHuman + " and copied object " + clonedMammalHuman + " are equal : " + (mammalHuman.equals(clonedMammalHuman)) + "\n"); 39 | 40 | } 41 | 42 | } 43 | 44 | class Mammal { 45 | 46 | protected String type; 47 | 48 | public Mammal(String type) { 49 | this.type = type; 50 | } 51 | 52 | public Mammal(Mammal original) { 53 | this.type = original.type; 54 | } 55 | 56 | public String getType() { 57 | return type; 58 | } 59 | 60 | public void setType(String type) { 61 | this.type = type; 62 | } 63 | 64 | public Mammal cloneObject() { 65 | return new Mammal(this); 66 | } 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | 73 | Mammal mammal = (Mammal) o; 74 | 75 | if (!type.equals(mammal.type)) return false; 76 | 77 | return true; 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return type.hashCode(); 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "Mammal{" + "type='" + type + "'}"; 88 | } 89 | } 90 | 91 | class Human extends Mammal { 92 | 93 | protected String name; 94 | 95 | public Human(String type, String name) { 96 | super(type); 97 | this.name = name; 98 | } 99 | 100 | public Human(Human original) { 101 | super(original.type); 102 | this.name = original.name; 103 | } 104 | 105 | public String getName() { 106 | return name; 107 | } 108 | 109 | public void setName(String name) { 110 | this.name = name; 111 | } 112 | 113 | @Override 114 | public Human cloneObject() { 115 | return new Human(this); 116 | } 117 | 118 | @Override 119 | public boolean equals(Object o) { 120 | if (this == o) return true; 121 | if (o == null || getClass() != o.getClass()) return false; 122 | if (!super.equals(o)) return false; 123 | 124 | Human human = (Human) o; 125 | 126 | if (!type.equals(human.type)) return false; 127 | if (!name.equals(human.name)) return false; 128 | 129 | return true; 130 | } 131 | 132 | @Override 133 | public int hashCode() { 134 | int result = super.hashCode(); 135 | result = 31 * result + name.hashCode(); 136 | return result; 137 | } 138 | 139 | @Override 140 | public String toString() { 141 | return "Human{" + "type='" + type + "', name='" + name + "'}"; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/sssp/DijkstraAlgorithm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.sssp; 2 | 3 | /** 4 | * Dijkstra's single source shortest path (sssp) algorithm to find single source shortest path in directed graph, 5 | * It works only on positive weight edges, 6 | * It might run exponentially if there is a negative weight edge or if there is a negative weight cycle. 7 | * It is a greedy algorithm and is somewhat similar to Prims MST algorithm. 8 | * 9 | * Time complexity = O(E.logV), In worst case E = V^2, Which wor case time complexity = O(V^2.logV) 10 | * Space complexity = O(E+V) 11 | * 12 | * @author Naresh Joshi 13 | */ 14 | public class DijkstraAlgorithm { 15 | 16 | public static void main(String[] args) { 17 | Graph graph = new Graph(6); 18 | graph.addEdge(0, 1, 4); 19 | graph.addEdge(0, 2, 7); 20 | graph.addEdge(1, 2, 8); 21 | graph.addEdge(1, 3, 13); 22 | graph.addEdge(1, 4, 11); 23 | graph.addEdge(2, 3, 12); 24 | graph.addEdge(2, 4, 10); 25 | graph.addEdge(3, 4, 9); 26 | graph.addEdge(3, 5, 15); 27 | graph.addEdge(4, 5, 14); 28 | 29 | System.out.println("For below tree:"); 30 | System.out.println( 31 | " /0\\\n" + 32 | " / \\ \n" + 33 | " 4/ \\7\n" + 34 | " / 8 \\\n" + 35 | " 1 ------- 2\n" + 36 | " | \\11 12/|\n" + 37 | " 13| \\ / | 10\n" + 38 | " | / \\ |\n" + 39 | " | / \\ |\n" + 40 | " | / \\ |\n" + 41 | " 3 ------- 4\n" + 42 | " \\ 9 /\n" + 43 | " 15\\ /14\n" + 44 | " \\ /\n" + 45 | " \\5/" 46 | ); 47 | 48 | int source = 0; 49 | int[] dist = dijkstraShortestPath(graph, source); 50 | 51 | for (int i = 0; i < dist.length; i++) { 52 | System.out.println(String.format("Minimum distance of %d from source %d is %d", i, source, dist[i])); 53 | } 54 | } 55 | 56 | private static int[] dijkstraShortestPath(Graph graph, int source) { 57 | int[] dist = new int[graph.V]; 58 | int[] parent = new int[graph.V]; 59 | boolean[] inTree = new boolean[graph.V]; 60 | 61 | for (int i = 0; i < graph.V; i++) { 62 | dist[i] = Integer.MAX_VALUE; 63 | parent[i] = -1; 64 | inTree[i] = false; 65 | } 66 | 67 | dist[source] = 0; 68 | 69 | for (int i = 0; i < graph.V - 1; i++) { 70 | 71 | int v = findMinDistance(dist, inTree); 72 | inTree[v] = true; 73 | 74 | for (int u = 0; u < graph.V; u++) { 75 | int w = graph.weight(v, u); 76 | if (!inTree[u] && w != 0 && (dist[v] + w < dist[u])) { 77 | dist[u] = dist[v] + w; 78 | parent[u] = v; 79 | } 80 | } 81 | } 82 | 83 | System.out.println("After running Dijkstra's algo, transformed tree below contains below edges: "); 84 | for (int i = 0; i < parent.length; i++) { 85 | if (parent[i] != -1) 86 | System.out.println(String.format("Edge %d --> %d", parent[i], i)); 87 | } 88 | 89 | return dist; 90 | } 91 | 92 | private static int findMinDistance(int[] dist, boolean[] inTree) { 93 | int minDistance = Integer.MAX_VALUE; 94 | int minDistanceVertex = 0; 95 | for (int v = 0; v < dist.length; v++) { 96 | if (!inTree[v] && dist[v] < minDistance) { 97 | minDistance = dist[v]; 98 | minDistanceVertex = v; 99 | } 100 | } 101 | return minDistanceVertex; 102 | } 103 | 104 | private static class Graph { 105 | int V, E = 0; 106 | int[][] adjMatrix; 107 | 108 | public Graph(int V) { 109 | this.V = V; 110 | adjMatrix = new int[V][V]; 111 | } 112 | 113 | public int weight(int from, int to) { 114 | return adjMatrix[from][to] != 0 ? adjMatrix[from][to] : adjMatrix[to][from]; 115 | } 116 | 117 | public void addEdge(int from, int to, int weight) { 118 | E++; 119 | adjMatrix[from][to] = weight; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/mst/KruskalsAlgoWithParentDSAndSize.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.mst; 2 | 3 | import java.util.Arrays; 4 | 5 | public class KruskalsAlgoWithParentDSAndSize { 6 | public static void main(String[] args) { 7 | Graph graph = new Graph(6, 10); 8 | graph.addEdge(0, 1, 4); 9 | graph.addEdge(0, 2, 7); 10 | graph.addEdge(1, 2, 8); 11 | graph.addEdge(1, 3, 13); 12 | graph.addEdge(1, 4, 11); 13 | graph.addEdge(2, 3, 12); 14 | graph.addEdge(2, 4, 10); 15 | graph.addEdge(3, 4, 9); 16 | graph.addEdge(3, 5, 15); 17 | graph.addEdge(4, 5, 14); 18 | 19 | System.out.println("For below tree:"); 20 | System.out.println( 21 | " /0\\\n" + 22 | " / \\ \n" + 23 | " 4/ \\7\n" + 24 | " / 8 \\\n" + 25 | " 1 ------- 2\n" + 26 | " | \\11 12/|\n" + 27 | " 13| \\ / | 10\n" + 28 | " | / \\ |\n" + 29 | " | / \\ |\n" + 30 | " | / \\ |\n" + 31 | " 3 ------- 4\n" + 32 | " \\ 9 /\n" + 33 | " 15\\ /14\n" + 34 | " \\ /\n" + 35 | " \\5/" 36 | ); 37 | 38 | Graph MST = findMST(graph); 39 | Edge[] edges = MST.edges; 40 | 41 | System.out.println("Minimum spanning tree generated through KruskalsAlgo contains edges:"); 42 | for (int i = 0; i < edges.length; i++) { 43 | System.out.println(edges[i]); 44 | } 45 | } 46 | 47 | 48 | private static Graph findMST(Graph graph) { 49 | Edge[] edges = graph.edges; 50 | Arrays.sort(edges); 51 | 52 | int[] parent = new int[graph.V]; 53 | int[] size = new int[graph.V]; 54 | for (int i = 0; i < graph.V; i++) { 55 | parent[i] = i; 56 | size[i] = 1; 57 | } 58 | 59 | int counter = 0; 60 | Edge[] mstEdges = new Edge[graph.V - 1]; 61 | for (int i = 0; i < graph.E; i++) { 62 | Edge edge = edges[i]; 63 | 64 | int x = find(edge.from, parent); 65 | int y = find(edge.to, parent); 66 | if (x != y) { 67 | mstEdges[counter++] = edge; 68 | union(x, y, parent, size); 69 | } 70 | } 71 | 72 | return new Graph(graph.V, mstEdges); 73 | } 74 | 75 | private static void union(int x, int y, int[] parent, int[] size) { 76 | // Merging smaller sized tree into larger size tree 77 | // Summing up size of bigger tree by smaller tree 78 | // Marking size of smaller sized tree 0 79 | if (size[x] <= size[y]) { 80 | parent[x] = y; 81 | size[y] = size[y] + size[x]; 82 | size[x] = 0; 83 | } else { 84 | parent[y] = x; 85 | size[x] = size[x] + size[y]; 86 | size[y] = 0; 87 | } 88 | } 89 | 90 | private static int find(int x, int[] parent) { 91 | int temp = x; 92 | while (temp != parent[temp]) 93 | temp = parent[temp]; 94 | return temp; 95 | } 96 | 97 | private static class Graph { 98 | public int V, E; 99 | public Edge[] edges; 100 | 101 | public int size = 0; 102 | 103 | public Graph(int V, int E) { 104 | this.V = V; 105 | this.E = E; 106 | this.edges = new Edge[E]; 107 | } 108 | 109 | public Graph(int V, Edge[] edges) { 110 | this.V = V; 111 | this.edges = edges; 112 | this.E = edges.length; 113 | } 114 | 115 | public void addEdge(int from, int to, int weight) { 116 | edges[size++] = new Edge(from, to, weight); 117 | } 118 | } 119 | 120 | private static class Edge implements Comparable { 121 | public int from, to, weight; 122 | 123 | public Edge(int from, int to, int weight) { 124 | this.from = from; 125 | this.to = to; 126 | this.weight = weight; 127 | } 128 | 129 | @Override 130 | public int compareTo(Edge o) { 131 | return Integer.compare(this.weight, o.weight); 132 | } 133 | 134 | @Override 135 | public String toString() { 136 | return String.format("%d -> %d with weight=%d", from, to, weight); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/logics/MaximumSubArraySum.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.logics; 2 | 3 | public class MaximumSubArraySum { 4 | public static void main(String[] args) { 5 | int[] arr1 = new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}; 6 | System.out.println(findMaxSubArraySumUsing3Loops(arr1)); 7 | System.out.println(findMaxSubArraySumUsing2Loops(arr1)); 8 | System.out.println(findMaxSubArraySumUsingDnC(arr1, 0, arr1.length - 1)); 9 | System.out.println(findMaxSubArraySumUsingDnC2(arr1, 0, arr1.length - 1)[3]); 10 | System.out.println(findMaxSubArraySumUsing1Loop(arr1)); 11 | 12 | 13 | int[] arr2 = new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4, 4}; 14 | System.out.println(findMaxSubArraySumUsing3Loops(arr2)); 15 | System.out.println(findMaxSubArraySumUsing2Loops(arr2)); 16 | System.out.println(findMaxSubArraySumUsingDnC(arr2, 0, arr2.length - 1)); 17 | System.out.println(findMaxSubArraySumUsingDnC2(arr2, 0, arr2.length - 1)[3]); 18 | System.out.println(findMaxSubArraySumUsing1Loop(arr2)); 19 | } 20 | 21 | // O(n^3) 22 | public static int findMaxSubArraySumUsing3Loops(int[] arr) { 23 | int maxSum = arr[0]; 24 | for (int i = 0; i < arr.length; i++) { 25 | for (int j = i; j < arr.length; j++) { 26 | int sum = 0; 27 | for (int k = i; k <= j; k++) { 28 | sum += arr[k]; 29 | } 30 | 31 | maxSum = Math.max(maxSum, sum); 32 | } 33 | } 34 | return maxSum; 35 | } 36 | 37 | // O(n^2) 38 | public static int findMaxSubArraySumUsing2Loops(int[] arr) { 39 | int maxSum = arr[0]; 40 | for (int i = 0; i < arr.length; i++) { 41 | int sum = 0; 42 | for (int j = i; j < arr.length; j++) { 43 | sum += arr[j]; 44 | maxSum = Math.max(maxSum, sum); 45 | } 46 | } 47 | return maxSum; 48 | } 49 | 50 | // O(nlogn) 51 | public static int findMaxSubArraySumUsingDnC(int[] arr, int start, int end) { 52 | if (end == start) 53 | return arr[start]; 54 | 55 | int mid = (start + end) / 2; 56 | 57 | int leftArrSum = findMaxSubArraySumUsingDnC(arr, start, mid); 58 | int rightArrSum = findMaxSubArraySumUsingDnC(arr, mid + 1, end); 59 | int crossingArrSum = findMaxCrossingSum(arr, start, mid, end); 60 | 61 | return Math.max(Math.max(leftArrSum, rightArrSum), crossingArrSum); 62 | } 63 | 64 | private static int findMaxCrossingSum(int[] arr, int start, int mid, int end) { 65 | 66 | int leftArrSum = Integer.MIN_VALUE; 67 | int rightArrSum = Integer.MIN_VALUE; 68 | 69 | int sum = 0; 70 | for (int i = mid; i >= start; i--) { 71 | sum += arr[i]; 72 | leftArrSum = Math.max(leftArrSum, sum); 73 | } 74 | 75 | sum = 0; 76 | for (int i = mid + 1; i <= end; i++) { 77 | sum += arr[i]; 78 | rightArrSum = Math.max(rightArrSum, sum); 79 | } 80 | 81 | return leftArrSum + rightArrSum; 82 | } 83 | 84 | // O(n) 85 | // Uses more for less technique, more parameters and returns for less calculation 86 | public static int[] findMaxSubArraySumUsingDnC2(int[] arr, int start, int end) { 87 | if (end == start) 88 | return new int[]{arr[start], arr[start], arr[start], arr[start]}; // Array represents TS, MPS, MSS, MAS 89 | 90 | int mid = (start + end) / 2; 91 | 92 | int[] leftSumsArr = findMaxSubArraySumUsingDnC2(arr, start, mid); 93 | int[] rightSumsArr = findMaxSubArraySumUsingDnC2(arr, mid + 1, end); 94 | 95 | return findMaxCrossingSum(leftSumsArr, rightSumsArr); 96 | } 97 | 98 | private static int[] findMaxCrossingSum(int[] leftSumsArr, int[] rightSumsArr) { 99 | return new int[]{ 100 | leftSumsArr[0] + rightSumsArr[0], // TS1 + TS2 101 | Math.max(leftSumsArr[1], leftSumsArr[0] + rightSumsArr[1]), // MAX(MPS1, TS1+MPS2) 102 | Math.max(leftSumsArr[2] + rightSumsArr[0], rightSumsArr[2]), // MAX(MSS1+TS2, MSS2) 103 | Math.max(Math.max(leftSumsArr[3], rightSumsArr[3]), leftSumsArr[2] + rightSumsArr[1]) // MAX(MAS1, MAS2, MSS1+MPS2) 104 | }; 105 | } 106 | 107 | // Kadane's Algorithm, we can create dp array and store best possible sub array sum for given index 108 | // arr -2, 1, -3, 4, -1, 2, 1, -5, 4 109 | // dp -2, (1|(1-2))=1, (-3|1-3)=-2, (4|4-2)=4, (-1|4-1)=3, (2|3+2)=5, (1|1+5)=6, (-5|6-5)=1, (4|4+1)=5 110 | // By looking at dp we can see max sub array sum is 6 111 | // O(n) 112 | public static int findMaxSubArraySumUsing1Loop(int[] arr) { 113 | 114 | int maxSum = arr[0]; 115 | int bestSum = arr[0]; 116 | for (int i = 1; i < arr.length; i++) { 117 | bestSum = Math.max(arr[i], arr[i] + bestSum); 118 | maxSum = Math.max(maxSum, bestSum); 119 | } 120 | return maxSum; 121 | } 122 | 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/DeepCloningUsingSerializationExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | import java.io.ObjectOutputStream; 8 | import java.io.Serializable; 9 | import java.time.LocalDate; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import java.util.Objects; 13 | 14 | /** 15 | * See complete articles on below links. 16 | * 17 | * https://www.programmingmitra.com/2019/08/how-to-deep-clone-an-object-using-java-in-memory-serialization.html, 18 | * https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html, 19 | * https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html, 20 | * https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html, 21 | * https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html, 22 | * https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html 23 | * https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html 24 | * 25 | * @author Naresh Joshi 26 | */ 27 | public class DeepCloningUsingSerializationExample 28 | { 29 | public static void main(String[] args) throws IOException, ClassNotFoundException 30 | { 31 | Employee emp = new Employee("Naresh Joshi", LocalDate.now(), Arrays.asList("Java", "Scala", "Spring")); 32 | System.out.println("Employee object: " + emp); 33 | 34 | // Deep cloning `emp` object by using our `deepClone` method. 35 | Employee clonedEmp = emp.deepClone(); 36 | System.out.println("Cloned employee object: " + clonedEmp); 37 | 38 | System.out.println(); 39 | 40 | // All of this will print false because both object are separate 41 | System.out.println(emp == clonedEmp); 42 | System.out.println(emp.getDoj() == clonedEmp.getDoj()); 43 | System.out.println(emp.getSkills() == clonedEmp.getSkills()); 44 | 45 | System.out.println(); 46 | 47 | // All of this will print true because `clonedEmp` is a deep clone of `emp` and both have same content 48 | System.out.println(Objects.equals(emp, clonedEmp)); 49 | System.out.println(Objects.equals(emp.getDoj(), clonedEmp.getDoj())); 50 | System.out.println(Objects.equals(emp.getSkills(), clonedEmp.getSkills())); 51 | } 52 | 53 | static class Employee implements Serializable 54 | { 55 | private static final long serialVersionUID = 2L; 56 | 57 | private String name; 58 | private LocalDate doj; 59 | private List skills; 60 | 61 | public Employee(String name, LocalDate doj, List skills) 62 | { 63 | this.name = name; 64 | this.doj = doj; 65 | this.skills = skills; 66 | } 67 | 68 | public String getName() 69 | { 70 | return name; 71 | } 72 | 73 | public LocalDate getDoj() 74 | { 75 | return doj; 76 | } 77 | 78 | public List getSkills() 79 | { 80 | return skills; 81 | } 82 | 83 | // Method to deep clone an object using in memory serialization. 84 | public Employee deepClone() throws IOException, ClassNotFoundException 85 | { 86 | // First serializing the object and its state to memory using ByteArrayOutputStream instead of FileOutputStream. 87 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 88 | ObjectOutputStream out = new ObjectOutputStream(bos); 89 | out.writeObject(this); 90 | 91 | // And then deserializing it from memory using ByteArrayOutputStream instead of FileInputStream, 92 | // Deserialization process will create a new object with the same state as in the serialized object. 93 | ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 94 | ObjectInputStream in = new ObjectInputStream(bis); 95 | return (Employee) in.readObject(); 96 | } 97 | 98 | @Override 99 | public String toString() 100 | { 101 | return String.format("Employee{name='%s', doj=%s, skills=%s}", name, doj, skills); 102 | } 103 | 104 | @Override 105 | public boolean equals(Object o) 106 | { 107 | if (this == o) 108 | { 109 | return true; 110 | } 111 | if (o == null || getClass() != o.getClass()) 112 | { 113 | return false; 114 | } 115 | 116 | Employee employee = (Employee) o; 117 | 118 | return Objects.equals(name, employee.name) && 119 | Objects.equals(doj, employee.doj) && 120 | Objects.equals(skills, employee.skills); 121 | } 122 | 123 | @Override 124 | public int hashCode() 125 | { 126 | return Objects.hash(name, doj, skills); 127 | } 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/SerializationExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | import java.io.ObjectOutputStream; 8 | import java.io.Serializable; 9 | 10 | /** 11 | * See complete articles on below links. 12 | * 13 | * https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html, 14 | * https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html, 15 | * https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html 16 | * 17 | * @author Naresh Joshi 18 | */ 19 | public class SerializationExample 20 | { 21 | 22 | public static void main(String[] args) throws IOException, ClassNotFoundException 23 | { 24 | Employee empObj = new Employee("Shanti", "Prasad", "Sharma", 25, "IT"); 25 | System.out.println("Object before serialization => " + empObj.toString()); 26 | 27 | // Serialization 28 | serialize(empObj); 29 | 30 | // Deserialization 31 | Employee deserialisedEmpObj = deserialize(); 32 | System.out.println("Object after deserialization => " + deserialisedEmpObj.toString()); 33 | } 34 | 35 | // Serialization code 36 | static void serialize(Employee empObj) throws IOException 37 | { 38 | try (FileOutputStream fos = new FileOutputStream("data.obj"); 39 | ObjectOutputStream oos = new ObjectOutputStream(fos)) 40 | { 41 | oos.writeObject(empObj); 42 | } 43 | } 44 | 45 | // Deserialization code 46 | static Employee deserialize() throws IOException, ClassNotFoundException 47 | { 48 | try (FileInputStream fis = new FileInputStream("data.obj"); 49 | ObjectInputStream ois = new ObjectInputStream(fis)) 50 | { 51 | return (Employee) ois.readObject(); 52 | } 53 | } 54 | 55 | // If we use Serializable interface, static and transient variables do not get serialized 56 | static class Employee implements Serializable 57 | { 58 | // This serialVersionUID field is necessary for Serializable as well as Externalizable to provide version control, 59 | // Compiler will provide this field if we do not provide it which might change if we modify class structure of our class, and we will get InvalidClassException, 60 | // If we provide a value to this field and do not change it, serialization-deserialization will not fail if we change our class structure. 61 | private static final long serialVersionUID = 2L; 62 | 63 | private final String firstName; // Serialization process do not invoke the constructor but it can assign values to final fields 64 | private transient String middleName; // transient variables will not be serialized, serialised object holds null 65 | private String lastName; 66 | private int age; 67 | private static String department; // static variables will not be serialized, serialised object holds null 68 | 69 | public Employee(String firstName, String middleName, String lastName, int age, String department) 70 | { 71 | this.firstName = firstName; 72 | this.middleName = middleName; 73 | this.lastName = lastName; 74 | this.age = age; 75 | Employee.department = department; 76 | 77 | validateAge(); 78 | } 79 | 80 | private void validateAge() 81 | { 82 | System.out.println("Validating age."); 83 | 84 | if (age < 18 || age > 70) 85 | { 86 | throw new IllegalArgumentException("Not a valid age to create an employee"); 87 | } 88 | } 89 | 90 | // Custom serialization logic, 91 | // This will allow us to have additional serialization logic on top of the default one e.g. encrypting object before serialization 92 | private void writeObject(ObjectOutputStream oos) throws IOException 93 | { 94 | System.out.println("Custom serialization logic invoked."); 95 | oos.defaultWriteObject(); // Calling the default serialization logic 96 | } 97 | 98 | // Custom deserialization logic 99 | // This will allow us to have additional deserialization logic on top of the default one e.g. decrypting object after deserialization 100 | private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException 101 | { 102 | System.out.println("Custom deserialization logic invoked."); 103 | 104 | ois.defaultReadObject(); // Calling the default deserialization logic 105 | 106 | // Age validation is just an example but there might some scenario where we might need to write some custom deserialization logic 107 | validateAge(); 108 | } 109 | 110 | @Override 111 | public String toString() 112 | { 113 | return String.format("Employee {firstName='%s', middleName='%s', lastName='%s', age='%s', department='%s'}", firstName, middleName, lastName, age, department); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/ExternalizableExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.io.Externalizable; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.ObjectInput; 8 | import java.io.ObjectInputStream; 9 | import java.io.ObjectOutput; 10 | import java.io.ObjectOutputStream; 11 | 12 | /** 13 | * See complete articles on below links. 14 | * 15 | * https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html, 16 | * https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html, 17 | * https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html 18 | * 19 | * @author Naresh Joshi 20 | */ 21 | public class ExternalizableExample 22 | { 23 | 24 | public static void main(String[] args) throws IOException, ClassNotFoundException 25 | { 26 | Employee empObj = new Employee("Shanti", "Sharma", 25, "IT"); 27 | System.out.println("Object before serialization => " + empObj.toString()); 28 | 29 | // Serialization 30 | serialize(empObj); 31 | 32 | // Deserialization 33 | Employee deserializedEmpObj = deserialize(); 34 | System.out.println("Object after deserialization => " + deserializedEmpObj.toString()); 35 | } 36 | 37 | // Serialization code 38 | static void serialize(Employee empObj) throws IOException 39 | { 40 | try (FileOutputStream fos = new FileOutputStream("data.obj"); 41 | ObjectOutputStream oos = new ObjectOutputStream(fos)) 42 | { 43 | oos.writeObject(empObj); 44 | } 45 | } 46 | 47 | // Deserialization code 48 | static Employee deserialize() throws IOException, ClassNotFoundException 49 | { 50 | try (FileInputStream fis = new FileInputStream("data.obj"); 51 | ObjectInputStream ois = new ObjectInputStream(fis)) 52 | { 53 | return (Employee) ois.readObject(); 54 | } 55 | } 56 | 57 | // Using Externalizable, complete serialization/deserialization logic becomes our responsibility, 58 | // We need to tell what to serialize using writeExternal() method and what to deserialize using readExternal(), 59 | // We can even serialize/deserialize static and transient variables, 60 | // With implementation of writeExternal() and readExternal(), methods writeObject() and readObject() becomes redundant and they do not get called. 61 | static class Employee implements Externalizable 62 | { 63 | // This serialVersionUID field is necessary for Serializable as well as Externalizable to provide version control, 64 | // Compiler will provide this field if we do not provide it which might change if we modify class structure of our class, and we will get InvalidClassException, 65 | // If we provide a value to this field and do not change it, serialization-deserialization will not fail if we change our class structure. 66 | private static final long serialVersionUID = 2L; 67 | 68 | private String firstName; 69 | private transient String lastName; // Using Externalizable, we can even serialize/deserialize transient variables, so declaring fields transient becomes unnecessary. 70 | private int age; 71 | private static String department; // Using Externalizable, we can even serialize/deserialize static variables according to our need. 72 | 73 | // Mandatory to have to make our class Externalizable 74 | // When an Externalizable object is reconstructed, the object is created using public no-arg constructor before the readExternal method is called. 75 | // If a public no-arg constructor is not present then a InvalidClassException is thrown at runtime. 76 | public Employee() 77 | { 78 | } 79 | 80 | // All-arg constructor to create objects manually 81 | public Employee(String firstName, String lastName, int age, String department) 82 | { 83 | this.firstName = firstName; 84 | this.lastName = lastName; 85 | this.age = age; 86 | Employee.department = department; 87 | 88 | validateAge(); 89 | } 90 | 91 | private void validateAge() 92 | { 93 | System.out.println("Validating age."); 94 | 95 | if (age < 18 || age > 70) 96 | { 97 | throw new IllegalArgumentException("Not a valid age to create an employee"); 98 | } 99 | } 100 | 101 | @Override 102 | // We need to tell what to serialize in writeExternal() method 103 | public void writeExternal(ObjectOutput out) throws IOException 104 | { 105 | System.out.println("Custom externalizable serialization logic invoked."); 106 | 107 | out.writeUTF(firstName); 108 | out.writeUTF(lastName); 109 | out.writeInt(age); 110 | out.writeUTF(department); 111 | } 112 | 113 | @Override 114 | // We need to tell what to deserialize in readExternal() method 115 | // The readExternal method must read the values in the same sequence and with the same types as were written by writeExternal 116 | public void readExternal(ObjectInput in) throws IOException 117 | { 118 | System.out.println("Custom externalizable serialization logic invoked."); 119 | 120 | firstName = in.readUTF(); 121 | lastName = in.readUTF(); 122 | age = in.readInt(); 123 | department = in.readUTF(); 124 | 125 | validateAge(); 126 | } 127 | 128 | @Override 129 | public String toString() 130 | { 131 | return String.format("Employee {firstName='%s', lastName='%s', age='%s', department='%s'}", firstName, lastName, age, department); 132 | } 133 | 134 | // Custom serialization logic, It will be called only if we have implemented Serializable instead of Externalizable. 135 | private void writeObject(ObjectOutputStream oos) throws IOException 136 | { 137 | System.out.println("Custom serialization logic invoked."); 138 | } 139 | 140 | // Custom deserialization logic, It will be called only if we have implemented Serializable instead of Externalizable. 141 | private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException 142 | { 143 | System.out.println("Custom deserialization logic invoked."); 144 | } 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/CloningExample.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | 8 | /** 9 | * @author Naresh Joshi 10 | * 11 | * See complete articles on below links 12 | * 13 | * https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html, 14 | * https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html, 15 | * https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html 16 | */ 17 | public class CloningExample { 18 | 19 | public static void main(String[] args) throws CloneNotSupportedException { 20 | 21 | City city = new City("Dehradun"); 22 | Country country = new Country("India"); 23 | Person person1 = new Person("Naresh", 10000, city, country); 24 | System.out.println(person1); 25 | 26 | Person person2 = person1.clone(); 27 | System.out.println(person2); 28 | 29 | // Evaluate false, because person1 and person2 holds different objects 30 | if (person1 == person2) { 31 | System.out.println("Both person1 and person2 holds same object"); 32 | } 33 | 34 | // Evaluate true, person1 and person2 are equal and have same content 35 | if (person1.equals(person2)) { 36 | System.out.println("But both person1 and person2 are equal and have same content"); 37 | } 38 | 39 | // Evaluate false 40 | if (person1.getCity() == person2.getCity()) { 41 | System.out.println("Both person1 and person2 have same city object"); 42 | } 43 | 44 | // Evaluate true, because we have not implemented clone in Country class 45 | if (person1.getCountry() == person2.getCountry()) { 46 | System.out.println("Both person1 and person2 have same country object"); 47 | } 48 | 49 | // Now lets change city and country object and print person1 and person2 50 | city.setName("Pune"); 51 | country.setName("IN"); 52 | 53 | // person1 will print new Pune city 54 | System.out.println(person1); 55 | // while person2 will still print Dehradun city because person2.city holds a separate city object 56 | System.out.println(person2); 57 | } 58 | } 59 | 60 | class Person implements Cloneable { 61 | private String name; // Will holds address of the String object which lives in SCP, instead of String object itself 62 | private int income; // Will hold bit representation of int, which is assigned to it 63 | private City city; // Will holds address of the City object which lives in heap, instead of City object 64 | private Country country; 65 | 66 | public String getName() { 67 | return name; 68 | } 69 | 70 | public void setName(String firstName) { 71 | this.name = firstName; 72 | } 73 | 74 | public int getIncome() { 75 | return income; 76 | } 77 | 78 | public void setIncome(int income) { 79 | this.income = income; 80 | } 81 | 82 | public City getCity() { 83 | return city; 84 | } 85 | 86 | public void setCity(City city) { 87 | this.city = city; 88 | } 89 | 90 | public Country getCountry() { 91 | return country; 92 | } 93 | 94 | public void setCountry(Country country) { 95 | this.country = country; 96 | } 97 | 98 | public Person(String name, int income, City city, Country country) { 99 | super(); 100 | this.name = name; 101 | this.income = income; 102 | this.city = city; 103 | this.country = country; 104 | } 105 | 106 | /** 107 | * Copy Constructor for cloning Person 108 | * 109 | * @param original 110 | */ 111 | public Person(Person original) { 112 | this.name = new String(original.name); 113 | this.income = original.income; 114 | this.city = new City(original.city); 115 | this.country = new Country(original.country); 116 | } 117 | 118 | /** 119 | * Method to clone person using Serialization 120 | * 121 | * @param original 122 | * @return 123 | */ 124 | public Person copy(Person original) { 125 | try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj")); 126 | ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"))) { 127 | 128 | // Serialization 129 | out.writeObject(original); 130 | 131 | //De Serialization 132 | return (Person) in.readObject(); 133 | } catch (Exception e) { 134 | throw new RuntimeException(e); // log exception or throw it by your own way 135 | } 136 | } 137 | 138 | // We can also create this any other name 139 | @Override 140 | public Person clone() throws CloneNotSupportedException { 141 | Person clonedObj = (Person) super.clone(); 142 | clonedObj.name = new String(this.name); 143 | clonedObj.city = this.city.clone(); 144 | return clonedObj; 145 | } 146 | 147 | @Override 148 | public String toString() { 149 | return "Person [name=" + name + ", income=" + income + ", city=" + city + ", country=" + country + "]"; 150 | } 151 | 152 | @Override 153 | public int hashCode() { 154 | int result = 1; 155 | result = 31 * result + ((city == null) ? 0 : city.hashCode()); 156 | result = 31 * result + ((country == null) ? 0 : country.hashCode()); 157 | result = 31 * result + income; 158 | result = 31 * result + ((name == null) ? 0 : name.hashCode()); 159 | return result; 160 | } 161 | 162 | @Override 163 | public boolean equals(Object obj) { 164 | if (this == obj) 165 | return true; 166 | if (obj == null) 167 | return false; 168 | if (getClass() != obj.getClass()) 169 | return false; 170 | Person other = (Person) obj; 171 | if (city == null) { 172 | if (other.city != null) 173 | return false; 174 | } else if (!city.equals(other.city)) 175 | return false; 176 | if (country == null) { 177 | if (other.country != null) 178 | return false; 179 | } else if (!country.equals(other.country)) 180 | return false; 181 | if (income != other.income) 182 | return false; 183 | if (name == null) { 184 | if (other.name != null) 185 | return false; 186 | } else if (!name.equals(other.name)) 187 | return false; 188 | return true; 189 | } 190 | } 191 | 192 | class City implements Cloneable { 193 | 194 | private String name; 195 | 196 | /** 197 | * Copy Constructor for cloning City 198 | * 199 | * @param original 200 | */ 201 | public City(City original) { 202 | this.name = new String(original.name); 203 | } 204 | 205 | public String getName() { 206 | return name; 207 | } 208 | 209 | public void setName(String name) { 210 | this.name = name; 211 | } 212 | 213 | public City(String name) { 214 | super(); 215 | this.name = name; 216 | } 217 | 218 | @Override 219 | public City clone() throws CloneNotSupportedException { 220 | return (City) super.clone(); 221 | } 222 | 223 | @Override 224 | public String toString() { 225 | return "City [name=" + name + "]"; 226 | } 227 | 228 | @Override 229 | public int hashCode() { 230 | final int prime = 31; 231 | int result = 1; 232 | result = prime * result + ((name == null) ? 0 : name.hashCode()); 233 | return result; 234 | } 235 | 236 | @Override 237 | public boolean equals(Object obj) { 238 | if (this == obj) 239 | return true; 240 | if (obj == null) 241 | return false; 242 | if (getClass() != obj.getClass()) 243 | return false; 244 | City other = (City) obj; 245 | if (name == null) { 246 | if (other.name != null) 247 | return false; 248 | } else if (!name.equals(other.name)) 249 | return false; 250 | return true; 251 | } 252 | } 253 | 254 | class Country { 255 | 256 | private String name; 257 | 258 | /** 259 | * Copy Constructor for cloning City 260 | * 261 | * @param original 262 | */ 263 | public Country(Country original) { 264 | this.name = new String(original.name); 265 | } 266 | 267 | public String getName() { 268 | return name; 269 | } 270 | 271 | public void setName(String name) { 272 | this.name = name; 273 | } 274 | 275 | public Country(String name) { 276 | super(); 277 | this.name = name; 278 | } 279 | 280 | @Override 281 | public String toString() { 282 | return "Country [name=" + name + "]"; 283 | } 284 | 285 | @Override 286 | public int hashCode() { 287 | int result = 1; 288 | result = 31 * result + ((name == null) ? 0 : name.hashCode()); 289 | return result; 290 | } 291 | 292 | @Override 293 | public boolean equals(Object obj) { 294 | if (this == obj) 295 | return true; 296 | if (obj == null) 297 | return false; 298 | if (getClass() != obj.getClass()) 299 | return false; 300 | Country other = (Country) obj; 301 | if (name == null) { 302 | if (other.name != null) 303 | return false; 304 | } else if (!name.equals(other.name)) 305 | return false; 306 | return true; 307 | } 308 | 309 | } 310 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/cryptography/RSA_Algorithm.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.cryptography; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Random; 5 | 6 | public class RSA_Algorithm { 7 | 8 | public static char[] multiply(char[] num1, char[] num2) { 9 | 10 | boolean isNegative = false; 11 | if (num1[0] == '-') { 12 | isNegative = true; 13 | num1[0] = 0; 14 | } 15 | 16 | if (num2[0] == '-') { 17 | isNegative = !isNegative; 18 | num2[0] = 0; 19 | } 20 | 21 | int m = num1.length; 22 | int n = num2.length; 23 | 24 | int[] result = new int[m + n]; 25 | for (int i = n - 1; i >= 0; i--) { 26 | int carry = 0; 27 | int position = m + i; 28 | for (int j = m - 1; j >= 0; j--) { 29 | int product = result[position] + carry + (toInt(num2[i]) * toInt(num1[j])); 30 | result[position] = product % 10; 31 | carry = product / 10; 32 | position--; 33 | } 34 | result[position] = carry; 35 | } 36 | 37 | String product = removeLeadingZeros(result); 38 | return (isNegative ? "-" + product : product).toCharArray(); 39 | } 40 | 41 | // Method expects both number to be positive 42 | public static String add(char[] num1, char[] num2) { 43 | int m = num1.length; 44 | int n = num2.length; 45 | int s = Math.max(m, n); 46 | 47 | int[] result = new int[s + 1]; 48 | while (m > 0 || n > 0) { 49 | char c1 = (m > 0) ? num1[m - 1] : '0'; 50 | char c2 = (n > 0) ? num2[n - 1] : '0'; 51 | 52 | int sum = toInt(c1) + toInt(c2) + result[s]; 53 | result[s] = sum % 10; 54 | result[s - 1] = sum / 10; 55 | 56 | m--; 57 | n--; 58 | s--; 59 | } 60 | 61 | return removeLeadingZeros(result); 62 | } 63 | 64 | // Method expects both number to be positive and num1 >= num2 65 | public static char[] subtract(char[] num1, char[] num2) { 66 | num1 = removeLeadingZeros(num1); 67 | num2 = removeLeadingZeros(num2); 68 | 69 | int m = num1.length; 70 | int n = num2.length; 71 | int s = Math.max(m, n); 72 | 73 | char[] result = new char[s]; 74 | while (m > 0 || n > 0) { 75 | int c1 = toInt((m > 0) ? num1[m - 1] : '0'); 76 | int c2 = toInt((n > 0) ? num2[n - 1] : '0'); 77 | 78 | if (c1 < c2 && m > 0) { 79 | c1 = 10 + c1; 80 | num1[m - 2] = toChar(toInt(num1[m - 2]) - 1); 81 | } 82 | 83 | result[s - 1] = toChar(c1 - c2); 84 | 85 | m--; 86 | n--; 87 | s--; 88 | } 89 | 90 | return removeLeadingZeros(result); 91 | } 92 | 93 | public static char[] divide(char[] num1, char[] num2) { 94 | return divideAndMod(num1, num2)[0].toCharArray(); 95 | } 96 | 97 | public static char[] mod(char[] num1, char[] num2) { 98 | return divideAndMod(num1, num2)[1].toCharArray(); 99 | } 100 | 101 | // gcd(num1, num2) = x.num1 + y.num2, where x is the mod inverse of num1 102 | public static char[] modInverse(char[] num1, char[] num2) { 103 | num1 = removeLeadingZeros(num1); 104 | num2 = removeLeadingZeros(num2); 105 | 106 | 107 | if (num2[0] == '0') { 108 | return "1".toCharArray(); 109 | } else { 110 | 111 | } 112 | 113 | return gcd(num2, mod(num1, num2)); 114 | } 115 | 116 | static int modInverse(int a, int b) { 117 | int m0 = b; 118 | int x = 1, y = 0; 119 | 120 | if (b == 1) 121 | return 0; 122 | 123 | while (a > 1) { 124 | // q is quotient 125 | int q = a / b; 126 | 127 | int t = b; 128 | 129 | // b is remainder now, process same as Euclid's algo 130 | b = a % b; 131 | a = t; 132 | t = y; 133 | 134 | // Update x and y 135 | y = x - q * y; 136 | x = t; 137 | } 138 | 139 | // Make x positive 140 | if (x < 0) 141 | x += m0; 142 | 143 | return x; 144 | } 145 | 146 | static int modPower(int x, int y, int p) { 147 | // Initialize result 148 | int res = 1; 149 | 150 | // Update x if it is more than or equal to p 151 | x = x % p; 152 | 153 | if (x == 0) 154 | return 0; // In case x is divisible by p; 155 | 156 | while (y > 0) { 157 | // If y is odd, multiply x with result 158 | if ((y & 1) == 1) 159 | res = (res * x) % p; 160 | 161 | // y must be even now 162 | y = y / 2; 163 | x = (x * x) % p; 164 | } 165 | return res; 166 | } 167 | 168 | public static String[] divideAndMod(char[] num1, char[] num2) { 169 | num1 = removeLeadingZeros(num1); 170 | num2 = removeLeadingZeros(num2); 171 | 172 | int quotient = 0; 173 | while (compare(num1, num2) >= 0) { 174 | num1 = subtract(num1, num2); 175 | quotient++; 176 | } 177 | 178 | return new String[]{String.valueOf(quotient), String.valueOf(num1)}; 179 | } 180 | 181 | public static char[] gcd(char[] num1, char[] num2) { 182 | num1 = removeLeadingZeros(num1); 183 | num2 = removeLeadingZeros(num2); 184 | 185 | if (num2[0] == '0') { 186 | return num1; 187 | } 188 | 189 | return gcd(num2, mod(num1, num2)); 190 | } 191 | 192 | public static int compare(char[] num1, char[] num2) { 193 | num1 = removeLeadingZeros(num1); 194 | num2 = removeLeadingZeros(num2); 195 | 196 | if (num1.length > num2.length) 197 | return 1; 198 | else if (num1.length < num2.length) 199 | return -1; 200 | 201 | int cmp = 0; 202 | for (int i = num1.length - 1; i >= 0; i--) { 203 | if (num1[i] < num2[i]) 204 | cmp = -1; 205 | else if (num1[i] > num2[i]) 206 | cmp = 1; 207 | } 208 | 209 | return cmp; 210 | } 211 | 212 | private static String removeLeadingZeros(int[] input) { 213 | StringBuilder sb = new StringBuilder(); 214 | for (int item : input) { 215 | if (!(sb.length() == 0 && item == 0)) { 216 | sb.append(item); 217 | } 218 | } 219 | return sb.length() == 0 ? "0" : sb.toString(); 220 | } 221 | 222 | private static char[] removeLeadingZeros(char[] input) { 223 | if (input[0] != '0') { 224 | return input; 225 | } 226 | 227 | StringBuilder sb = new StringBuilder(); 228 | for (char item : input) { 229 | if (!(sb.length() == 0 && item == '0')) { 230 | sb.append(item); 231 | } 232 | } 233 | return sb.length() == 0 ? new char[]{'0'} : sb.toString().toCharArray(); 234 | } 235 | 236 | private static int toInt(char character) { 237 | return character - '0'; 238 | } 239 | 240 | private static char toChar(int digit) { 241 | return (char) ('0' + digit); 242 | } 243 | 244 | private BigInteger N; 245 | private BigInteger e; 246 | private BigInteger d; 247 | 248 | public RSA_Algorithm() { 249 | this(1024); 250 | } 251 | 252 | public RSA_Algorithm(int bitLength) { 253 | Random r = new Random(); 254 | 255 | BigInteger p = BigInteger.probablePrime(bitLength, r); 256 | BigInteger q = BigInteger.probablePrime(bitLength, r); 257 | 258 | System.out.println(p); 259 | System.out.println(q); 260 | 261 | char[] product = multiply(p.toString().toCharArray(), q.toString().toCharArray()); 262 | N = new BigInteger(new String(product)); 263 | 264 | char[] pMinus1 = subtract(p.toString().toCharArray(), "1".toCharArray()); 265 | char[] qMinus1 = subtract(q.toString().toCharArray(), "1".toCharArray()); 266 | 267 | BigInteger phiN = new BigInteger(new String(multiply(pMinus1, qMinus1))); 268 | 269 | e = BigInteger.probablePrime(bitLength / 2, r); 270 | while (phiN.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phiN) < 0) { 271 | e = new BigInteger(add(e.toString().toCharArray(), "1".toCharArray())); 272 | } 273 | 274 | d = e.modInverse(phiN); 275 | } 276 | 277 | public byte[] encrypt(String plainText) { 278 | System.out.println(new BigInteger(plainText.getBytes()).modPow(e, N)); 279 | return new BigInteger(plainText.getBytes()).modPow(e, N).toByteArray(); 280 | } 281 | 282 | public String decrypt(byte[] cipherText) { 283 | return new String(new BigInteger(cipherText).modPow(d, N).toByteArray()); 284 | } 285 | 286 | public static void main(String[] args) { 287 | RSA_Algorithm rsa = new RSA_Algorithm(); 288 | 289 | String plainText = "Hello! I am Naresh"; 290 | 291 | System.out.println("Plain text: " + plainText); 292 | 293 | System.out.println("Encrypting..."); 294 | byte[] cipherText = rsa.encrypt(plainText); 295 | 296 | System.out.println("Cipher text: " + decode(cipherText)); 297 | 298 | // decrypt 299 | System.out.println("Decrypting..."); 300 | String decryptedPlainText = rsa.decrypt(cipherText); 301 | 302 | System.out.println("Decrypted plain text: " + decryptedPlainText); 303 | } 304 | 305 | private static String decode(byte[] bytes) { 306 | StringBuilder sb = new StringBuilder(); 307 | for (byte b : bytes) { 308 | sb.append(b); 309 | } 310 | return sb.toString(); 311 | } 312 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | This repository along with the [articles](https://github.com/njnareshjoshi/articles) repository contains coding examples for my blog [ProgrammingMitra](https://www.programmingmitra.com). 2 | 3 | ### Spring 4 | * [Introduction To Spring](https://www.programmingmitra.com/2016/05/introduction-to-spring.html) 5 | * [Spring Modular Architecture](https://www.programmingmitra.com/2018/07/spring-modular-architecture.html) 6 | 7 | ### Spring Data 8 | * [Spring Data JPA Auditing: Saving CreatedBy, CreatedDate, LastModifiedBy, LastModifiedDate Automatically](https://www.programmingmitra.com/2017/02/automatic-spring-data-jpa-auditing-saving-CreatedBy-createddate-lastmodifiedby-lastmodifieddate-automatically.html) 9 | * [JPA Auditing: Persisting Audit Logs Automatically Using EntityListeners](https://www.programmingmitra.com/2017/02/automatic-jpa-auditing-persisting-audit-logs-automatically-using-entityListeners.html) 10 | * [AutoWiring Spring Beans Into Classes Not Managed By Spring Like JPA Entity Listeners](https://www.programmingmitra.com/2017/03/AutoWiring-Spring-Beans-Into-Classes-Not-Managed-By-Spring-Like-JPA-Entity-Listeners.html) 11 | * [Implementing Our Own Custom Spring Data Solr Repository](https://www.programmingmitra.com/2016/01/how-to-write-custom-implementation-for.html) 12 | 13 | ### What In Java 14 | * [What is Variable Shadowing And Hiding In Java](https://www.programmingmitra.com/2018/02/what-is-variable-shadowing-and-hiding.html) 15 | * [Everything About Method Overloading Vs Method Overriding](https://www.programmingmitra.com/2017/05/everything-about-method-overloading-vs-method-overriding.html) 16 | * [Everything About ClassNotFoundException Vs NoClassDefFoundError](https://www.programmingmitra.com/2017/04/Difference-Between-ClassNotFoundException-and-NoClassDefFoundError.html) 17 | * [Java Cloning - Copy Constructor versus Cloning](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) 18 | * [Java Cloning And Types Of Cloning (Shallow And Deep) In Details With Example](https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html) 19 | * [Java Lambda Expression Explained With Example](https://www.programmingmitra.com/2016/06/java-lambda-expression-explained-with-example.html) 20 | * [What are JDK And JRE? JDK And JRE File Structure Explained](https://www.programmingmitra.com/2016/05/jdk-and-jre-file-structure.html) 21 | * [What are 5 Different Ways To Create Objects In Java? Explained With Example](https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html) 22 | * [Plain Old Java Object (POJO) Explained](https://www.programmingmitra.com/2016/05/plain-old-java-object-pojo-explained.html) 23 | * [Types Of References In Java(Strong Soft Weak Phantom)](https://www.programmingmitra.com/2016/05/types-of-references-in-javastrong-soft.html) 24 | * [What is Serialization? Everything About Java Serialization Explained With Example](https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html) 25 | 26 | ### Why In Java 27 | * [Java Integer Cache - Why Integer.valueOf(127) == Integer.valueOf(127) Is True](https://www.programmingmitra.com/2018/11/java-integer-cache.html) 28 | * [Why Instance Variable Of Super Class Is Not Overridden In Sub Class](https://www.programmingmitra.com/2018/11/why-instance-variable-of-super-class-is-not-overridden-In-sub-class.html) 29 | * [Why String is Immutable And Final In Java](https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html) 30 | * [Why String is Stored In String Constant Pool](https://www.programmingmitra.com/2018/02/why-string-is-stored-in-constant-pool.html) 31 | * [Why We Should Follow Method Overriding Rules](https://www.programmingmitra.com/2017/12/why-we-should-follow-method-overriding-rules.html) 32 | * [Why Should We Follow Method Overloading Rules](https://www.programmingmitra.com/2017/12/why-to-follow-method-overloading-rules.html) 33 | * [How Does JVM Handle Method Overloading And Overriding Internally](https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html) 34 | * [Java Cloning - Why Even Copy Constructors Are Not Sufficient](https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html) 35 | * [Java Cloning - Copy Constructor versus Cloning](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) 36 | * [Why An outer Java class can’t be static](https://www.programmingmitra.com/2016/10/why-outer-java-class-cant-be-static.html) 37 | * [Why An outer Java class can’t be private or protected](https://www.programmingmitra.com/2016/10/why-a-java-class-can-not-be-private-or-protected.html) 38 | * [Why Java is Purely Object Oriented Language Or Why Not](https://www.programmingmitra.com/2016/06/why-java-is-purely-object-oriented-or-why-not.html) 39 | * [Why Single Java Source File Can Not Have More Than One public class](https://www.programmingmitra.com/2016/05/Why-Single-Java-Source-File-Can-Not-Have-More-Than-One-public-class.html) 40 | 41 | ### How In Java 42 | * [How To Customize Serialization In Java By Using Externalizable Interface](https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html) 43 | * [What are 5 Different Ways To Create Objects In Java? Explained With Example](https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html) 44 | * [How To Create Objects By Using Reflection APIs In Java With Example](https://www.programmingmitra.com/2016/05/creating-objects-through-reflection-in-java-with-example.html) 45 | * [How To Install Multiple Versions Of Java On The Same Machine](https://www.programmingmitra.com/2019/03/how-to-install-multiple-versions-of-java-on-the-same-machine.html) 46 | * [How To Create An Immutable Class In Java With Example](https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html) 47 | * [How Does JVM Handle Polymorphism (Method Overloading And Method Overriding) Internally](https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html) 48 | * [Java Cloning - How Copy Constructors are Better Than Cloning](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) 49 | * [How To Create An Immutable Class In Java With Example](https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html) 50 | 51 | ### Useful Dev Tools 52 | * [How To Install Multiple Versions Of Java On The Same Machine](https://www.programmingmitra.com/2019/03/how-to-install-multiple-versions-of-java-on-the-same-machine.html) 53 | * [Project Lombok : The Boilerplate Code Extractor](https://www.programmingmitra.com/2017/01/Project-Lombok-The-Boilerplate-Code-Extractor.html) 54 | * [Useful Git Commands](https://www.programmingmitra.com/2019/01/useful-git-commands.html) 55 | 56 | ### ClassNotFoundException Vs NoClassDefFoundError 57 | * [Difference Between ClassNotFoundException And NoClassDefFoundError](https://www.programmingmitra.com/2017/04/Difference-Between-ClassNotFoundException-and-NoClassDefFoundError.html) 58 | 59 | ### Java Cloning Vs Copy Constructors Vs Defensive Copy Methods 60 | * [Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example](https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html) 61 | * [Java Cloning Copy Constructor Versus Object Clone Or Cloning](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) 62 | * [Java Cloning Why Copy Constructors Are Not Sufficient Or Good](https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html) 63 | 64 | ### Immutability In Java 65 | * [How To Create Immutable Class In Java](https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html) 66 | * [Why String Is Immutable And Final In Java](https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html) 67 | 68 | ### Java Integer Cache 69 | * [Java Integer Cache - Why Integer.valueOf(127) == Integer.valueOf(127) Is True](https://www.programmingmitra.com/2018/11/java-integer-cache.html) 70 | 71 | ### Java 8 - Lambda 72 | * [Java Lambda Expression Explained With Example](https://www.programmingmitra.com/2016/06/java-lambda-expression-explained-with-example.html) 73 | * [How To Install Multiple Versions Of Java On The Same Machine](https://www.programmingmitra.com/2019/03/how-to-install-multiple-versions-of-java-on-the-same-machine.html) 74 | 75 | ### Java Object Creation 76 | * [Different Ways To Create Objects In Java With Example](https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html) 77 | * [How To Create Objects By Using Reflection APIs In Java With Example](https://www.programmingmitra.com/2016/05/creating-objects-through-reflection-in-java-with-example.html) 78 | 79 | ### Java Method Overloading And Overriding 80 | * [Everything About Method Overloading Vs Method Overriding](https://www.programmingmitra.com/2017/05/everything-about-method-overloading-vs-method-overriding.html) 81 | * [Why We Should Follow Method Overriding Rules](https://www.programmingmitra.com/2017/12/why-we-should-follow-method-overriding-rules.html) 82 | * [How Does JVM Handle Method Overloading And Overriding Internally](https://www.programmingmitra.com/2017/05/how-does-jvm-handle-method-overriding-internally.html) 83 | * [Why Instance Variable Of Super Class Is Not Overridden In Sub Class](https://www.programmingmitra.com/2018/11/why-instance-variable-of-super-class-is-not-overridden-In-sub-class.html) 84 | 85 | ### Java Serialization And Externalization 86 | * [What is Serialization? Everything About Java Serialization Explained With Example](https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html) 87 | * [How To Customize Serialization In Java By Using Externalizable Interface](https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html) 88 | * [What are 5 Different Ways To Create Objects In Java? Explained With Example](https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html) 89 | -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/algos/graph/dag/TopologicalSortAndLongestPath.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.algos.graph.dag; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | import java.util.Stack; 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | /** 10 | * TopologicalSort And LongestPathCalculation 11 | * 1. Generate a DAG with random vertices, edges and weights 12 | * 2. Perform Topological Sort on DAG 13 | * 3. Calculate longest path for weighted and non-weighted DAG 14 | * 15 | * @author Naresh Joshi 16 | */ 17 | public class TopologicalSortAndLongestPath { 18 | public static void main(String[] args) { 19 | 20 | // Test 1 21 | // 1. Generate a DAG with random vertices, edges and weights 22 | DAG_UsingAdjacencyMatrix randomDagObj = new DAG_UsingAdjacencyMatrix(5); 23 | randomDagObj.generateRandomDAG(5); 24 | randomDagObj.printDag(); 25 | 26 | // 2. Perform Topological Sort on DAG 27 | randomDagObj.topologicalSort(); 28 | randomDagObj.topologicalSortRecursive(); 29 | 30 | // 3. Calculate longest path for weighted and non-weighted DAG 31 | randomDagObj.findLongestPath(); 32 | 33 | 34 | // Test 2 35 | DAG_UsingAdjacencyMatrix randomDagObj2 = new DAG_UsingAdjacencyMatrix(100); 36 | randomDagObj2.generateRandomDAG(90); 37 | randomDagObj2.printDag(); 38 | 39 | randomDagObj2.topologicalSort(); 40 | randomDagObj2.topologicalSortRecursive(); 41 | 42 | randomDagObj2.findLongestPath(); 43 | 44 | // Test 3 - Without random DAG 45 | /* 46 | dagObj represents below graph 47 | 0, 1, 0, 1, 0, 0 48 | 0, 0, 1, 1, 0, 0 49 | 0, 0, 0, 1, 1, 1 50 | 0, 0, 0, 0, 1, 1 51 | 0, 0, 0, 0, 1, 0 52 | 0, 0, 0, 0, 0, 0 53 | */ 54 | DAG_UsingAdjacencyMatrix dagObj = new DAG_UsingAdjacencyMatrix(6); 55 | dagObj.addEdge(0, 1); 56 | dagObj.addEdge(0, 3); 57 | dagObj.addEdge(1, 2); 58 | dagObj.addEdge(1, 3); 59 | dagObj.addEdge(2, 3); 60 | dagObj.addEdge(2, 4); 61 | dagObj.addEdge(2, 5); 62 | dagObj.addEdge(3, 4); 63 | dagObj.addEdge(3, 5); 64 | dagObj.addEdge(5, 4); 65 | 66 | dagObj.printDag(); 67 | dagObj.topologicalSort(); // It should like [0, 1, 2, 3, 5, 4] 68 | dagObj.topologicalSortRecursive(); // It should like [0, 1, 2, 3, 5, 4] 69 | dagObj.findLongestPath(); // Equal to 5 70 | 71 | // Test 4 - Without random DAG with weights on edges 72 | /* 73 | weightedDagObj represents below graph 74 | 0, 2, 0, 1, 0, 0 75 | 0, 0, 2, 1, 0, 0 76 | 0, 0, 0, 1, 1, 5 77 | 0, 0, 0, 0, 1, 1 78 | 0, 0, 0, 0, 0, 1 79 | 0, 0, 0, 0, 0, 0 80 | */ 81 | DAG_UsingAdjacencyMatrix weightedDagObj = new DAG_UsingAdjacencyMatrix(6); 82 | weightedDagObj.addEdge(0, 1, 2); 83 | weightedDagObj.addEdge(0, 3, 1); 84 | weightedDagObj.addEdge(1, 2, 2); 85 | weightedDagObj.addEdge(1, 3, 1); 86 | weightedDagObj.addEdge(2, 3, 1); 87 | weightedDagObj.addEdge(2, 4, 1); 88 | weightedDagObj.addEdge(2, 5, 5); 89 | weightedDagObj.addEdge(3, 4, 1); 90 | weightedDagObj.addEdge(3, 5, 1); 91 | weightedDagObj.addEdge(4, 5, 1); 92 | 93 | weightedDagObj.printDag(); 94 | weightedDagObj.findLongestPath(); 95 | } 96 | } 97 | 98 | class DAG_UsingAdjacencyMatrix { 99 | 100 | private final int[][] adjMatrix; 101 | 102 | // Will be used to construct adjacency matrix of inputted verticesSize. 103 | public DAG_UsingAdjacencyMatrix(int verticesSize) { 104 | System.out.println(); 105 | System.out.println("Generating a DAG with " + verticesSize + " vertices."); 106 | adjMatrix = new int[verticesSize][verticesSize]; 107 | } 108 | 109 | public void generateRandomDAG(int edgeSize) { 110 | int verticesSize = adjMatrix.length; 111 | 112 | // Creating edges with a random vertex and random weight 113 | for (int i = 0; i < edgeSize; i++) { 114 | int randomFromVertex = ThreadLocalRandom.current().nextInt(0, verticesSize); 115 | int randomToVertex = ThreadLocalRandom.current().nextInt(randomFromVertex, verticesSize); 116 | int randomWeight = ThreadLocalRandom.current().nextInt(0, 10); 117 | addEdge(randomFromVertex, randomToVertex, randomWeight); 118 | } 119 | } 120 | 121 | public void printDag() { 122 | // Printing randomly generated adjacency matrix. 123 | System.out.println("Generated Adjacency matrix"); 124 | for (int[] matrix : adjMatrix) { 125 | System.out.println(Arrays.toString(matrix)); 126 | } 127 | } 128 | 129 | // Method will add an edge to DAG for inputted vertices with default weight of 1. 130 | public void addEdge(int vertex1, int vertex2) { 131 | addEdge(vertex1, vertex2, 1); 132 | } 133 | 134 | // Method will add an edge to DAG for input vertices with inputted weight. 135 | public void addEdge(int vertex1, int vertex2, int weight) { 136 | // Validations to check if we are not creating cycles in our DAG 137 | if (vertex1 == vertex2) { 138 | System.out.println(String.format("Can not add edge %s->%s because it will form a cycle.", vertex1, vertex2)); 139 | } else if (adjMatrix[vertex2][vertex1] != 0) { 140 | System.out.println(String.format("Can not add edge %s->%s because and opposite edge %s->%s already exists.", vertex1, vertex2, vertex2, vertex1)); 141 | } else { 142 | adjMatrix[vertex1][vertex2] = weight; 143 | } 144 | } 145 | 146 | // Method will return a copy of adjacency matrix. 147 | public int[][] getAdjMatrix() { 148 | return adjMatrix.clone(); 149 | } 150 | 151 | // Method will topologically sort our dag and return vertices in a sorted array. 152 | public int[] topologicalSort() { 153 | int length = adjMatrix.length; 154 | int[] result = new int[length]; 155 | int[] visited = new int[length]; 156 | int[] inDegree = new int[length]; 157 | Queue queue = new LinkedList<>(); 158 | 159 | // Calculating in_degree of all vertices available within the DAG. 160 | for (int i = 0; i < length; i++) { 161 | for (int j = 0; j < length; j++) { 162 | // If there is an edge from vertex i to vertex j then increasing in_degree of vertex j. 163 | if (adjMatrix[i][j] != 0) { 164 | inDegree[j] = inDegree[j] + 1; 165 | } 166 | } 167 | } 168 | 169 | // Adding all vertices with in_degree == 0 to queue because these vertices are our starting point for topological order. 170 | // Also adding the nodes which we have visited to a visited array so we do not visit it again. 171 | for (int i = 0; i < length; i++) { 172 | if (inDegree[i] == 0) { 173 | queue.add(i); 174 | visited[i] = 1; 175 | } 176 | } 177 | 178 | int i = 0; 179 | // Looping through the while it is not empty and doing below mentioned steps: 180 | while (!queue.isEmpty()) { 181 | // 1. Removing a vertex from queue and adding it to result array. 182 | int vertex = queue.remove(); 183 | result[i++] = vertex; 184 | 185 | // 2. Iterating through the adjacency matrix and picking vertices which 186 | for (int j = 0; j < length; j++) { 187 | // 2.1. Have an edge from vertex to it and, 188 | // 2.2. Which are not in the visited array. 189 | if (adjMatrix[vertex][j] != 0 && visited[j] == 0) { 190 | 191 | // 3. Decreasing in_degree of those vertices 192 | inDegree[j] = inDegree[j] - 1; 193 | 194 | // 4. If decreased in_degree of the any of these vertices is 0 then putting those into queue and visited array, 195 | // Because now they are the next nodes which need to be picked for topological ordering. 196 | if (inDegree[j] == 0) { 197 | queue.add(j); 198 | visited[j] = 1; 199 | } 200 | } 201 | } 202 | } 203 | 204 | // Printing the final topological ordering and returning it. 205 | System.out.println("Topological ordering " + Arrays.toString(result)); 206 | return result; 207 | } 208 | 209 | // Method will recursively topological sort our dag and return vertices in a sorted array. 210 | public int[] topologicalSortRecursive() { 211 | int length = adjMatrix.length; 212 | int[] visited = new int[length]; 213 | Stack stack = new Stack<>(); 214 | // Iterating through all the vertices staring with 0. 215 | for (int i = 0; i < length; i++) { 216 | if (visited[i] == 0) { 217 | // Calling supporting recursive method for all unvisited vertices. 218 | topologicalSortRecursive(adjMatrix, length, i, visited, stack); 219 | } 220 | } 221 | 222 | int count = 0; 223 | int[] result = new int[length]; 224 | // After all recursive call completion, stack will be storing the topological ordering in reverse order. 225 | // So popping from stack and putting it our result array. 226 | while (!stack.isEmpty()) { 227 | result[count++] = stack.pop(); 228 | } 229 | 230 | // Printing the final topological ordering and returning it. 231 | System.out.println("Recursively calculated topological ordering " + Arrays.toString(result)); 232 | return result; 233 | } 234 | 235 | private void topologicalSortRecursive(int[][] dag, int length, int currentVertex, int[] visited, Stack stack) { 236 | // Marking currentVertex as visited. 237 | visited[currentVertex] = 1; 238 | for (int j = 0; j < length; j++) { 239 | if (dag[currentVertex][j] != 0 && visited[j] == 0) { 240 | // If there is an edge from currentVertex to vertex j and vertex j is not visited yet then calculating its topological ordering recursively. 241 | topologicalSortRecursive(dag, length, j, visited, stack); 242 | } 243 | } 244 | 245 | // After all recursive calls to generate topological ordering of currentVertex finishes, pushing currentVertex into stack 246 | stack.push(currentVertex); 247 | } 248 | 249 | // Method to find longest path for the dag 250 | public int findLongestPath() { 251 | int length = adjMatrix.length; 252 | int[] inDegree = new int[length]; 253 | int[] path = new int[length]; 254 | 255 | // Calculating in_degree of all vertices available within the DAG. 256 | for (int i = 0; i < length; i++) { 257 | for (int j = 0; j < length; j++) { 258 | // If there is an edge from vertex i to vertex j then increasing in_degree of vertex j. 259 | // dag[i][j] holds the weight for edge i --> j. 260 | if (adjMatrix[i][j] != 0) { 261 | inDegree[j] = inDegree[j] + 1; 262 | } 263 | } 264 | } 265 | 266 | int longestPath = 0; 267 | // Iterating through all the vertices staring with 0. 268 | for (int i = 0; i < length; i++) { 269 | if (inDegree[i] == 0) { 270 | // Calling supporting recursive method for all unvisited vertices, supporting will store longest path for vertex i at path[i] 271 | findLongestPath(adjMatrix, length, i, path); 272 | 273 | // If longest path for vertex i at path[i] is greater then longestPath then putting path[i] into longestPath. 274 | longestPath = Math.max(longestPath, path[i]); 275 | } 276 | } 277 | 278 | System.out.println("Longest path " + longestPath); 279 | 280 | return longestPath; 281 | } 282 | 283 | private void findLongestPath(int[][] dag, int length, int currentVertex, int[] path) { 284 | for (int j = 0; j < length; j++) { 285 | // If there is an edge from currentVertex to vertex j and vertex j with some weight. 286 | if (dag[currentVertex][j] != 0) { 287 | // Then calculating longest path for j its topological ordering recursively. 288 | findLongestPath(dag, length, j, path); 289 | // Updating longest path for currentVertex stored at path[currentVertex] if it is less then (weight of currentVertex --> j + longest path for j) 290 | path[currentVertex] = Math.max(path[currentVertex], dag[currentVertex][j] + path[j]); 291 | } 292 | } 293 | } 294 | 295 | } -------------------------------------------------------------------------------- /src/org/programming/mitra/exercises/ds/RedBlackTree.java: -------------------------------------------------------------------------------- 1 | package org.programming.mitra.exercises.ds; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | import static org.programming.mitra.exercises.ds.RedBlackTree.Color.BLACK; 8 | import static org.programming.mitra.exercises.ds.RedBlackTree.Color.RED; 9 | 10 | /** 11 | * Red Black Tree (RBT) is a self-balanced binary search tree with one extra info of color at each node. 12 | * The leaf nodes of RBT do not contain data and called extended nodes or explicit nodes, 13 | * These can be simply be Null or a single sentinel node. 14 | * 15 | * Complexities 16 | * Space O(n) 17 | * Search O(log n) 18 | * Insert O(log n) 19 | * Delete O(log n) 20 | * 21 | * Rules for RBT 22 | * 1. Every node is either red or back, 23 | * 2. Root node is always black, 24 | * 3. All external nodes or leaf nodes are black 25 | * 4. If a node is red, then both its children are black, A red node can never has red child, 26 | * 5. Every path from a given node to any of its descendant leaf nodes goes through the same number of black nodes. 27 | * 28 | * Black Depth of a node = number of black nodes from the root to that node, 29 | * Black Height of the tree = number of black nodes in any path from the root to the leaves, 30 | * According to point 5, Black Depth of any leaf node = Black Height of tree 31 | * 32 | * Which means the path from the root to the farthest leaf is no more than twice as long as the path from the root to the nearest leaf. 33 | * 34 | * @author Naresh Joshi 35 | */ 36 | public class RedBlackTree { 37 | 38 | /** 39 | * Main insert method of red black tree. 40 | */ 41 | public Node insert(Node root, int data) { 42 | System.out.println("Inserting into tree : " + data); 43 | return insert(null, root, data); 44 | } 45 | 46 | /** 47 | * Main delete method of red black tree. 48 | */ 49 | public Node delete(Node root, int data) { 50 | System.out.println("Deleting from tree : " + data); 51 | AtomicReference rootReference = new AtomicReference<>(); 52 | delete(root, data, rootReference); 53 | if (rootReference.get() == null) { 54 | return root; 55 | } else { 56 | return rootReference.get(); 57 | } 58 | } 59 | 60 | /** 61 | * Main print method of red black tree. 62 | */ 63 | public void printInOrderTree(Node root) { 64 | printInOrderTree(root, 0); 65 | System.out.println(); 66 | } 67 | 68 | /** 69 | * Main validate method of red black tree. 70 | */ 71 | public boolean validateRedBlackTree(Node root) { 72 | 73 | if (root == null) { 74 | return true; 75 | } 76 | //check if root is black 77 | if (root.color != BLACK) { 78 | System.out.print("Root is not black"); 79 | return false; 80 | } 81 | //Use of AtomicInteger solely because java does not provide any other mutable int wrapper. 82 | AtomicInteger blackCount = new AtomicInteger(0); 83 | //make sure black count is same on all path and there is no red red relationship 84 | return checkBlackNodesCount(root, blackCount, 0) && noRedRedParentChild(root, BLACK); 85 | } 86 | 87 | private void rightRotate(Node root, boolean changeColor) { 88 | Node parent = root.parent; 89 | root.parent = parent.parent; 90 | if (parent.parent != null) { 91 | if (parent.parent.rightChild == parent) { 92 | parent.parent.rightChild = root; 93 | } else { 94 | parent.parent.leftChild = root; 95 | } 96 | } 97 | Node right = root.rightChild; 98 | root.rightChild = parent; 99 | parent.parent = root; 100 | parent.leftChild = right; 101 | if (right != null) { 102 | right.parent = parent; 103 | } 104 | if (changeColor) { 105 | root.color = BLACK; 106 | parent.color = RED; 107 | } 108 | } 109 | 110 | private void leftRotate(Node root, boolean changeColor) { 111 | Node parent = root.parent; 112 | root.parent = parent.parent; 113 | if (parent.parent != null) { 114 | if (parent.parent.rightChild == parent) { 115 | parent.parent.rightChild = root; 116 | } else { 117 | parent.parent.leftChild = root; 118 | } 119 | } 120 | Node left = root.leftChild; 121 | root.leftChild = parent; 122 | parent.parent = root; 123 | parent.rightChild = left; 124 | if (left != null) { 125 | left.parent = parent; 126 | } 127 | if (changeColor) { 128 | root.color = BLACK; 129 | parent.color = RED; 130 | } 131 | } 132 | 133 | private Optional findSiblingNode(Node root) { 134 | Node parent = root.parent; 135 | if (isLeftChild(root)) { 136 | return Optional.ofNullable(parent.rightChild.isLeaf ? null : parent.rightChild); 137 | } else { 138 | return Optional.ofNullable(parent.leftChild.isLeaf ? null : parent.leftChild); 139 | } 140 | } 141 | 142 | private boolean isLeftChild(Node root) { 143 | Node parent = root.parent; 144 | if (parent.leftChild == root) { 145 | return true; 146 | } else { 147 | return false; 148 | } 149 | } 150 | 151 | private Node insert(Node parent, Node root, int data) { 152 | if (root == null || root.isLeaf) { 153 | //if parent is not null means tree is not empty so create a red leaf node 154 | if (parent != null) { 155 | return createRedNode(parent, data); 156 | } else { 157 | //otherwise create a black root node if tree is empty 158 | return createBlackNode(data); 159 | } 160 | } 161 | 162 | //duplicate insertion is not allowed for this tree. 163 | if (root.data == data) { 164 | throw new IllegalArgumentException("Duplicate date " + data); 165 | } 166 | //if we go on left side then isLeft will be true 167 | //if we go on right side then isLeft will be false. 168 | boolean isLeft; 169 | if (root.data > data) { 170 | Node left = insert(root, root.leftChild, data); 171 | //if left becomes root parent means rotation 172 | //happened at lower level. So just return left 173 | //so that nodes at upper level can set their 174 | //child correctly 175 | if (left == root.parent) { 176 | return left; 177 | } 178 | //set the left child returned to be left of root node 179 | root.leftChild = left; 180 | //set isLeft to be true 181 | isLeft = true; 182 | } else { 183 | Node right = insert(root, root.rightChild, data); 184 | //if right becomes root parent means rotation 185 | //happened at lower level. So just return right 186 | //so that nodes at upper level can set their 187 | //child correctly 188 | if (right == root.parent) { 189 | return right; 190 | } 191 | //set the right child returned to be right of root node 192 | root.rightChild = right; 193 | //set isRight to be true 194 | isLeft = false; 195 | } 196 | 197 | if (isLeft) { 198 | //if we went to left side check to see Red-Red conflict 199 | //between root and its left child 200 | if (root.color == RED && root.leftChild.color == RED) { 201 | //get the sibling of root. It is returning optional means 202 | //sibling could be empty 203 | Optional sibling = findSiblingNode(root); 204 | //if sibling is empty or of BLACK color 205 | if (!sibling.isPresent() || sibling.get().color == BLACK) { 206 | //check if root is left child of its parent 207 | if (isLeftChild(root)) { 208 | //this creates left left situation. So do one right rotate 209 | rightRotate(root, true); 210 | } else { 211 | //this creates left-right situation so do one right rotate followed 212 | //by left rotate 213 | 214 | //do right rotation without change in color. So sending false. 215 | //when right rotation is done root becomes right child of its left 216 | //child. So make root = root.parent because its left child before rotation 217 | //is new root of this subtree. 218 | rightRotate(root.leftChild, false); 219 | //after rotation root should be root's parent 220 | root = root.parent; 221 | //then do left rotate with change of color 222 | leftRotate(root, true); 223 | } 224 | 225 | } else { 226 | //we have sibling color as RED. So change color of root 227 | //and its sibling to Black. And then change color of their 228 | //parent to red if their parent is not a root. 229 | root.color = BLACK; 230 | sibling.get().color = BLACK; 231 | //if parent's parent is not null means parent is not root. 232 | //so change its color to RED. 233 | if (root.parent.parent != null) { 234 | root.parent.color = RED; 235 | } 236 | } 237 | } 238 | } else { 239 | //this is mirror case of above. So same comments as above. 240 | if (root.color == RED && root.rightChild.color == RED) { 241 | Optional sibling = findSiblingNode(root); 242 | if (!sibling.isPresent() || sibling.get().color == BLACK) { 243 | if (!isLeftChild(root)) { 244 | leftRotate(root, true); 245 | } else { 246 | leftRotate(root.rightChild, false); 247 | root = root.parent; 248 | rightRotate(root, true); 249 | } 250 | } else { 251 | root.color = BLACK; 252 | sibling.get().color = BLACK; 253 | if (root.parent.parent != null) { 254 | root.parent.color = RED; 255 | } 256 | } 257 | } 258 | } 259 | return root; 260 | } 261 | 262 | /** 263 | * Using atomicreference because java does not provide mutable wrapper. Its like 264 | * double pointer in C. 265 | */ 266 | private void delete(Node root, int data, AtomicReference rootReference) { 267 | if (root == null || root.isLeaf) { 268 | return; 269 | } 270 | if (root.data == data) { 271 | //if node to be deleted has 0 or 1 null children then we have 272 | //deleteOneChild use case as discussed in video. 273 | if (root.rightChild.isLeaf || root.leftChild.isLeaf) { 274 | deleteOneChild(root, rootReference); 275 | } else { 276 | //otherwise look for the inorder successor in right subtree. 277 | //replace inorder successor data at root data. 278 | //then delete inorder successor which should have 0 or 1 not null child. 279 | Node inorderSuccessor = findSmallest(root.rightChild); 280 | root.data = inorderSuccessor.data; 281 | delete(root.rightChild, inorderSuccessor.data, rootReference); 282 | } 283 | } 284 | //search for the node to be deleted. 285 | if (root.data < data) { 286 | delete(root.rightChild, data, rootReference); 287 | } else { 288 | delete(root.leftChild, data, rootReference); 289 | } 290 | } 291 | 292 | private Node findSmallest(Node root) { 293 | Node prev = null; 294 | while (root != null && !root.isLeaf) { 295 | prev = root; 296 | root = root.leftChild; 297 | } 298 | return prev != null ? prev : root; 299 | } 300 | 301 | /** 302 | * Assumption that node to be deleted has either 0 or 1 non leaf child 303 | */ 304 | private void deleteOneChild(Node nodeToBeDelete, AtomicReference rootReference) { 305 | Node child = nodeToBeDelete.rightChild.isLeaf ? nodeToBeDelete.leftChild : nodeToBeDelete.rightChild; 306 | //replace node with either one not null child if it exists or null child. 307 | replaceNode(nodeToBeDelete, child, rootReference); 308 | //if the node to be deleted is BLACK. See if it has one red child. 309 | if (nodeToBeDelete.color == BLACK) { 310 | //if it has one red child then change color of that child to be Black. 311 | if (child.color == RED) { 312 | child.color = BLACK; 313 | } else { 314 | //otherwise we have double black situation. 315 | deleteCase1(child, rootReference); 316 | } 317 | } 318 | } 319 | 320 | 321 | /** 322 | * If double black node becomes root then we are done. Turning it into 323 | * single black node just reduces one black in every path. 324 | */ 325 | private void deleteCase1(Node doubleBlackNode, AtomicReference rootReference) { 326 | if (doubleBlackNode.parent == null) { 327 | rootReference.set(doubleBlackNode); 328 | return; 329 | } 330 | deleteCase2(doubleBlackNode, rootReference); 331 | } 332 | 333 | /** 334 | * If sibling is red and parent and sibling's children are black then rotate it 335 | * so that sibling becomes black. Double black node is still double black so we need 336 | * further processing. 337 | */ 338 | private void deleteCase2(Node doubleBlackNode, AtomicReference rootReference) { 339 | Node siblingNode = findSiblingNode(doubleBlackNode).get(); 340 | if (siblingNode.color == RED) { 341 | if (isLeftChild(siblingNode)) { 342 | rightRotate(siblingNode, true); 343 | } else { 344 | leftRotate(siblingNode, true); 345 | } 346 | if (siblingNode.parent == null) { 347 | rootReference.set(siblingNode); 348 | } 349 | } 350 | deleteCase3(doubleBlackNode, rootReference); 351 | } 352 | 353 | /** 354 | * If sibling, sibling's children and parent are all black then turn sibling into red. 355 | * This reduces black node for both the paths from parent. Now parent is new double black 356 | * node which needs further processing by going back to case1. 357 | */ 358 | private void deleteCase3(Node doubleBlackNode, AtomicReference rootReference) { 359 | 360 | Node siblingNode = findSiblingNode(doubleBlackNode).get(); 361 | 362 | if (doubleBlackNode.parent.color == BLACK && siblingNode.color == BLACK && siblingNode.leftChild.color == BLACK 363 | && siblingNode.rightChild.color == BLACK) { 364 | siblingNode.color = RED; 365 | deleteCase1(doubleBlackNode.parent, rootReference); 366 | } else { 367 | deleteCase4(doubleBlackNode, rootReference); 368 | } 369 | } 370 | 371 | /** 372 | * If sibling color is black, parent color is red and sibling's children color is black then swap color b/w sibling 373 | * and parent. This increases one black node on double black node path but does not affect black node count on 374 | * sibling path. We are done if we hit this situation. 375 | */ 376 | private void deleteCase4(Node doubleBlackNode, AtomicReference rootReference) { 377 | Node siblingNode = findSiblingNode(doubleBlackNode).get(); 378 | if (doubleBlackNode.parent.color == RED && siblingNode.color == BLACK && siblingNode.leftChild.color == BLACK 379 | && siblingNode.rightChild.color == BLACK) { 380 | siblingNode.color = RED; 381 | doubleBlackNode.parent.color = BLACK; 382 | return; 383 | } else { 384 | deleteCase5(doubleBlackNode, rootReference); 385 | } 386 | } 387 | 388 | /** 389 | * If sibling is black, double black node is left child of its parent, siblings right child is black 390 | * and sibling's left child is red then do a right rotation at siblings left child and swap colors. 391 | * This converts it to delete case6. It will also have a mirror case. 392 | */ 393 | private void deleteCase5(Node doubleBlackNode, AtomicReference rootReference) { 394 | Node siblingNode = findSiblingNode(doubleBlackNode).get(); 395 | if (siblingNode.color == BLACK) { 396 | if (isLeftChild(doubleBlackNode) && siblingNode.rightChild.color == BLACK && siblingNode.leftChild.color == RED) { 397 | rightRotate(siblingNode.leftChild, true); 398 | } else if (!isLeftChild(doubleBlackNode) && siblingNode.leftChild.color == BLACK && siblingNode.rightChild.color == RED) { 399 | leftRotate(siblingNode.rightChild, true); 400 | } 401 | } 402 | deleteCase6(doubleBlackNode, rootReference); 403 | } 404 | 405 | /** 406 | * If sibling is black, double black node is left child of its parent, sibling left child is black and sibling's right child is 407 | * red, sibling takes its parent color, parent color becomes black, sibling's right child becomes black and then do 408 | * left rotation at sibling without any further change in color. This removes double black and we are done. This 409 | * also has a mirror condition. 410 | */ 411 | private void deleteCase6(Node doubleBlackNode, AtomicReference rootReference) { 412 | Node siblingNode = findSiblingNode(doubleBlackNode).get(); 413 | siblingNode.color = siblingNode.parent.color; 414 | siblingNode.parent.color = BLACK; 415 | if (isLeftChild(doubleBlackNode)) { 416 | siblingNode.rightChild.color = BLACK; 417 | leftRotate(siblingNode, false); 418 | } else { 419 | siblingNode.leftChild.color = BLACK; 420 | rightRotate(siblingNode, false); 421 | } 422 | if (siblingNode.parent == null) { 423 | rootReference.set(siblingNode); 424 | } 425 | } 426 | 427 | private void replaceNode(Node root, Node child, AtomicReference rootReference) { 428 | child.parent = root.parent; 429 | if (root.parent == null) { 430 | rootReference.set(child); 431 | } else { 432 | if (isLeftChild(root)) { 433 | root.parent.leftChild = child; 434 | } else { 435 | root.parent.rightChild = child; 436 | } 437 | } 438 | } 439 | 440 | private void printInOrderTree(Node node, int height) { 441 | if (node == null || node.isLeaf) { 442 | return; 443 | } 444 | 445 | height++; 446 | 447 | printInOrderTree(node.leftChild, height); 448 | System.out.print(node.data + " " + (node.color == BLACK ? "B" : "R") + ", "); 449 | printInOrderTree(node.rightChild, height); 450 | } 451 | 452 | private boolean noRedRedParentChild(Node root, Color parentColor) { 453 | if (root == null) { 454 | return true; 455 | } 456 | if (root.color == RED && parentColor == RED) { 457 | return false; 458 | } 459 | 460 | return noRedRedParentChild(root.leftChild, root.color) && noRedRedParentChild(root.rightChild, root.color); 461 | } 462 | 463 | private boolean checkBlackNodesCount(Node root, AtomicInteger blackCount, int currentCount) { 464 | 465 | if (root.color == BLACK) { 466 | currentCount++; 467 | } 468 | 469 | if (root.leftChild == null && root.rightChild == null) { 470 | if (blackCount.get() == 0) { 471 | blackCount.set(currentCount); 472 | return true; 473 | } else { 474 | return currentCount == blackCount.get(); 475 | } 476 | } 477 | return checkBlackNodesCount(root.leftChild, blackCount, currentCount) && checkBlackNodesCount(root.rightChild, blackCount, currentCount); 478 | } 479 | 480 | public static void main(String[] args) { 481 | RedBlackTree redBlackTree = new RedBlackTree(); 482 | 483 | Node root = redBlackTree.insert(null, 10); 484 | root = redBlackTree.insert(root, 15); 485 | root = redBlackTree.insert(root, -10); 486 | root = redBlackTree.insert(root, 20); 487 | root = redBlackTree.insert(root, 30); 488 | root = redBlackTree.insert(root, 40); 489 | root = redBlackTree.insert(root, 50); 490 | root = redBlackTree.insert(root, 25); 491 | root = redBlackTree.insert(root, 17); 492 | root = redBlackTree.insert(root, 21); 493 | root = redBlackTree.insert(root, 24); 494 | root = redBlackTree.insert(root, 28); 495 | root = redBlackTree.insert(root, 34); 496 | root = redBlackTree.insert(root, 32); 497 | root = redBlackTree.insert(root, 26); 498 | root = redBlackTree.insert(root, 35); 499 | root = redBlackTree.insert(root, 19); 500 | root = redBlackTree.insert(root, -15); 501 | 502 | System.out.println("Inorder RBT looks like:"); 503 | redBlackTree.printInOrderTree(root); 504 | 505 | root = redBlackTree.delete(root, 50); 506 | root = redBlackTree.delete(root, 40); 507 | root = redBlackTree.delete(root, -10); 508 | root = redBlackTree.delete(root, 15); 509 | root = redBlackTree.delete(root, 17); 510 | root = redBlackTree.delete(root, 24); 511 | 512 | System.out.println("Final Inorder RBT looks like:"); 513 | redBlackTree.printInOrderTree(root); 514 | 515 | System.out.println("Is tree balanced : " + redBlackTree.validateRedBlackTree(root)); 516 | } 517 | 518 | public enum Color { 519 | RED, BLACK 520 | } 521 | 522 | public static class Node { 523 | int data; 524 | Color color; 525 | 526 | Node parent; 527 | Node leftChild; 528 | Node rightChild; 529 | 530 | boolean isLeaf; 531 | } 532 | 533 | private static Node createBlackNode(int data) { 534 | Node node = new Node(); 535 | node.data = data; 536 | node.color = BLACK; 537 | node.leftChild = createLeafNode(node); 538 | node.rightChild = createLeafNode(node); 539 | return node; 540 | } 541 | 542 | private static Node createRedNode(Node parent, int data) { 543 | Node node = new Node(); 544 | node.parent = parent; 545 | node.data = data; 546 | node.color = RED; 547 | node.leftChild = createLeafNode(node); 548 | node.rightChild = createLeafNode(node); 549 | return node; 550 | } 551 | 552 | private static Node createLeafNode(Node parent) { 553 | Node leafNode = new Node(); 554 | leafNode.parent = parent; 555 | leafNode.color = BLACK; 556 | leafNode.isLeaf = true; 557 | return leafNode; 558 | } 559 | } 560 | 561 | --------------------------------------------------------------------------------