├── .gitignore ├── README.md └── src ├── algorithms ├── recursion │ ├── Factorial.java │ ├── Fibonacci.java │ └── ReverseString.java └── sorting │ ├── BubbleSort.java │ ├── InsertionSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ └── SelectionSort.java ├── data_structures ├── arrays │ ├── MergeSortedArray.java │ ├── MyArray.java │ └── ReverseString.java ├── graphs │ └── MyGraph.java ├── hash_tables │ ├── FirstRecurringCharacter.java │ ├── MyHashTable.java │ └── MyNode.java ├── linked_lists │ ├── doubly │ │ ├── MyDoublyLinkedList.java │ │ └── MyDoublyLinkedNode.java │ └── singly │ │ ├── MySinglyLinkedList.java │ │ └── MySinglyLinkedNode.java ├── queues │ ├── using_linked_list │ │ ├── MyQueue.java │ │ └── MySinglyLinkedNode.java │ └── using_stack │ │ └── MyQueue.java ├── stacks │ ├── using_array │ │ └── MyStack.java │ └── using_linked_list │ │ ├── MySinglyLinkedNode.java │ │ └── MyStack.java └── trees │ └── binary_search_tree │ ├── MyBinaryNode.java │ └── MyBinarySearchTree.java ├── dynamic_programming └── DynamicFibonacci.java └── interview_question ├── CommonItems.java ├── amazon_interview_questions └── ValidParentheses.java ├── facebook_interview_questions └── NumberOfIslands.java └── google_interview_questions └── TrappingRainWater.java /.gitignore: -------------------------------------------------------------------------------- 1 | core/java/jar/sf2-core.jar 2 | *.class 3 | frc/java/jar/sf2-frc.jar 4 | 5 | # Created by https://www.gitignore.io/api/gradle,intellij+all 6 | 7 | ### Intellij+all ### 8 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 9 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 10 | 11 | # User-specific stuff 12 | .idea/**/workspace.xml 13 | .idea/**/tasks.xml 14 | .idea/**/usage.statistics.xml 15 | .idea/**/dictionaries 16 | .idea/**/shelf 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/modules.xml 39 | # .idea/*.iml 40 | # .idea/modules 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | ### Intellij+all Patch ### 76 | # Ignores the whole .idea folder and all .iml files 77 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 78 | 79 | .idea/ 80 | 81 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 82 | 83 | *.iml 84 | modules.xml 85 | .idea/misc.xml 86 | *.ipr 87 | 88 | ### Gradle ### 89 | .gradle 90 | /build/ 91 | 92 | # Ignore Gradle GUI config 93 | gradle-app.setting 94 | 95 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 96 | !gradle-wrapper.jar 97 | 98 | # Cache of project 99 | .gradletasknamecache 100 | 101 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 102 | # gradle/wrapper/gradle-wrapper.properties 103 | 104 | 105 | # End of https://www.gitignore.io/api/gradle,intellij+all 106 | 107 | imgui.ini 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Structures-and-Algorithms 2 | ## Data structures 3 | 1. Array 4 | 2. Graphs 5 | 3. Hash tables (HashMap) 6 | 4. Linked Lists 7 | 5 Queues 8 | 6. Stacks 9 | 7. BST 10 | ## Algorithms 11 | 1. Recursion 12 | 1. Factorial 13 | 2. Fibonacci - Includes a simple recursive with time complexity of O(n) 14 | 3. ReverseString 15 | 1. Sorting 16 | 1. Bubble sort 17 | 2. Selection sort 18 | 3. Insertion sort 19 | 4. Merge sort 20 | 5. Quick sort 21 | ## Dynamic programming 22 | 1. Dynamic Fibonacci 23 | ## Interview Questions 24 | 1. Common items 25 | -------------------------------------------------------------------------------- /src/algorithms/recursion/Factorial.java: -------------------------------------------------------------------------------- 1 | package algorithms.recursion; 2 | 3 | public class Factorial { 4 | // Write two functions that finds the factorial of any number. 5 | // One should use recursive, the other should just use a for loop 6 | 7 | public static long findFactorialRecursively(long number) { // O(n) 8 | if (number == 1) { 9 | return 1; 10 | } 11 | return number * findFactorialRecursively(number - 1); 12 | } 13 | 14 | public static long findFactorialIteratively(long number) { // O(n) 15 | long result = 1; 16 | for (long i = number; i > 0; i--) { 17 | result *= i; 18 | } 19 | return result; 20 | } 21 | 22 | public static void main(String[] args) { 23 | System.out.println(findFactorialRecursively(10000)); 24 | System.out.println(findFactorialIteratively(1000000)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/algorithms/recursion/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package algorithms.recursion; 2 | 3 | public class Fibonacci { 4 | // Given a number N return the index value of the Fibonacci sequence, where the sequence is: 5 | 6 | // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 ... 7 | // the pattern of the sequence is that each value is the sum of the 2 previous values, that means that for N=5 → 2+3 8 | 9 | //For example: fibonacciRecursive(6) should return 8 10 | 11 | static int num = 0; 12 | public static int fibonacciRecursively(int n) { //O(2^n) 13 | if(n < 2) { 14 | return n; 15 | } 16 | return fibonacciRecursively(n - 1) + fibonacciRecursively(n - 2); 17 | } 18 | 19 | static int fibonacciRecursivelyEfficient(int n, int val, int prev) { //O(n) 20 | if (n == 0) { 21 | return prev; 22 | } 23 | if (n == 1) { 24 | return val; 25 | } 26 | return fibonacciRecursivelyEfficient(n - 1, val + prev, val); 27 | } 28 | 29 | public static int fibonacciIteratively(int n) { //O(n) 30 | if(n == 0) { 31 | return 0; 32 | } 33 | int result = 1; 34 | int lastNumber = 0; 35 | int temp; 36 | for (int i = 1; i < n; i++) { 37 | temp = result; 38 | result += lastNumber; 39 | lastNumber = temp; 40 | } 41 | return result; 42 | } 43 | 44 | public static void main(String[] args) { 45 | num 46 | = 0; 47 | System.out.println(fibonacciIteratively(10)); 48 | System.out.println(fibonacciRecursivelyEfficient(50, 1 , 0)); 49 | System.out.println(fibonacciRecursively(50)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/algorithms/recursion/ReverseString.java: -------------------------------------------------------------------------------- 1 | package algorithms.recursion; 2 | 3 | public class ReverseString { 4 | 5 | //Implement a function that reverses a string using iteration...and then recursion! 6 | 7 | public static String reverseStringRecursively(String string) { //O(n) - Where "n" is the length of the string 8 | if(string.length() == 0) { 9 | return ""; 10 | } 11 | return reverseStringRecursively(string.substring(1)) + string.charAt(0); 12 | } 13 | 14 | public static String reverseStringIteratively(String string) { //O(n) 15 | StringBuilder result = new StringBuilder(); 16 | for (int i = 0; i < string.length(); i++) { 17 | result.append(string.charAt(string.length() - 1 - i)); 18 | } 19 | return result.toString(); 20 | } 21 | 22 | public static void main(String[] args) { 23 | System.out.println(reverseStringRecursively("123456")); 24 | System.out.println(reverseStringIteratively("123456")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/algorithms/sorting/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | public class BubbleSort { 6 | 7 | public static Integer[] bubbleSort(Integer[] array) { 8 | int temp; 9 | for (int i = 0; i < array.length; i++) { 10 | for (int j = 0; j < array.length - 1; j++) { 11 | if (array[j] > array[j + 1]) { 12 | temp = array[j]; 13 | array[j] = array[j + 1]; 14 | array[j + 1] = temp; 15 | } 16 | } 17 | } 18 | return array; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Integer[] array = {8, 1, 56, 4, 7, 1, 87, 0}; 23 | Arrays.stream(bubbleSort(array)).forEach(System.out::println); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/algorithms/sorting/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | public class InsertionSort { 8 | 9 | public static Integer[] insertionSort(Integer[] array) { 10 | List list = new LinkedList<>(Arrays.asList(array)); //Using linked list so shifting will be efficient 11 | for (int i = 1; i < list.size(); i++) { //Fixed: i start at i = 1 12 | if (list.get(i) <= list.get(0)) { //Fixed: duplicate values sort by changing to "<=" 13 | //Checking if current number is suppose to be first 14 | list.add(0, list.get(i)); //Moving the number to first position 15 | list.remove(i + 1); 16 | } else { 17 | // only sort number smaller than number on the left of it. 18 | // This is the part of insertion sort that makes it fast 19 | // if the array is almost sorted. 20 | if (list.get(i) < list.get(i - 1)) { 21 | //find where number should go 22 | for (int j = 1; j < i; j++) { 23 | if (list.get(i) >= list.get(j - 1) && list.get(i) < list.get(j)) { 24 | //move number to the correct spot 25 | list.add(j, list.get(i)); 26 | list.remove(i + 1); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | return list.toArray(new Integer[0]); 33 | } 34 | 35 | public static void main(String[] args) { 36 | Integer[] array = {1, 8, 54, 9, 65, 1, 100, 0, 45}; 37 | Arrays.stream(insertionSort(array)).forEach(System.out::println); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/algorithms/sorting/MergeSort.java: -------------------------------------------------------------------------------- 1 | package algorithms.sorting; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class MergeSort { 8 | 9 | public static Integer[] mergeSort(Integer[] array) { 10 | return mergeSort(new ArrayList<>(Arrays.asList(array))).toArray(new Integer[0]); 11 | } 12 | 13 | public static List mergeSort(List array) { 14 | if (array.size() == 1) { 15 | return array; 16 | } 17 | // Split Array in into right and left 18 | List left = array.subList(0, array.size() / 2); 19 | System.out.println("Splitting left: " + left); 20 | List right = array.subList(array.size() / 2, array.size()); 21 | System.out.println("Splitting Right: " + right); 22 | return merge(mergeSort(left), mergeSort(right)); 23 | } 24 | 25 | public static List merge(List left, List right) { 26 | List merged = new ArrayList<>(); 27 | int leftIndex = 0; 28 | int rightIndex = 0; 29 | while (leftIndex < left.size() && rightIndex < right.size()) { //Keep merging until we done with one of the sides 30 | if (left.get(leftIndex) <= right.get(rightIndex)) { //Fixed: "<" to "<=", this what makes the merge sort "stable" 31 | merged.add(left.get(leftIndex)); 32 | leftIndex++; 33 | } else { 34 | merged.add(right.get(rightIndex)); 35 | rightIndex++; 36 | } 37 | } 38 | merged.addAll(left.subList(leftIndex, left.size())); //Merging all "leftovers" elements as is because we know they are sorted 39 | merged.addAll(right.subList(rightIndex, right.size())); //Same 40 | System.out.println("Merged: " + merged); 41 | return merged; 42 | } 43 | 44 | public static void main(String[] args) { 45 | Integer[] array = {1, 8, 54, 9, 65, 1, 100, 0, 45, 50, 0, 90, 30, 46}; 46 | Arrays.stream(mergeSort(array)).forEach(System.out::println); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/algorithms/sorting/QuickSort.java: -------------------------------------------------------------------------------- 1 | package algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | public class QuickSort { 6 | 7 | public static Integer[] quickSort(Integer[] array, int left, int right){ 8 | int pivot; 9 | int partitionIndex; 10 | 11 | if(left < right) { 12 | pivot = right; 13 | System.out.println("Part: " + Arrays.asList(array).subList(left, right + 1) + " by " + array[pivot]); 14 | partitionIndex = partition(array, pivot, left, right); 15 | System.out.println("Result: " + Arrays.asList(array).subList(left, right + 1)); 16 | 17 | //sort left and right 18 | quickSort(array, left, partitionIndex - 1); 19 | quickSort(array, partitionIndex + 1, right); 20 | } 21 | return array; 22 | } 23 | 24 | public static int partition(Integer[] array, int pivot, int left, int right){ 25 | int pivotValue = array[pivot]; 26 | int partitionIndex = left; 27 | 28 | for(int i = left; i < right; i++) { 29 | if(array[i] < pivotValue){ 30 | swap(array, i, partitionIndex); 31 | partitionIndex++; 32 | } 33 | } 34 | swap(array, right, partitionIndex); 35 | return partitionIndex; 36 | } 37 | 38 | private static void swap(Integer[] array, int index1, int index2) { 39 | int temp = array[index1]; 40 | array[index1] = array[index2]; 41 | array[index2] = temp; 42 | } 43 | 44 | public static void main(String[] args) { 45 | Integer[] array = {1, 9, 54, 8, 65, 1, 100, 0, 45, 50, 0, 90, 30, 46}; 46 | System.out.println(Arrays.asList(quickSort(array, 0 , array.length - 1))); 47 | } 48 | } -------------------------------------------------------------------------------- /src/algorithms/sorting/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | public class SelectionSort { 6 | 7 | public static Integer[] selectionSort(Integer[] array) { 8 | for (int i = 0; i < array.length; i++) { 9 | int minValue = array[i]; 10 | int minIndex = i; 11 | for (int j = i + 1; j < array.length; j++) { 12 | if (minValue > array[j]) { //Searching min value and it's index 13 | minValue = array[j]; 14 | minIndex = j; 15 | } 16 | } 17 | int temp = array[i]; //Swapping the min value found 18 | array[i] = minValue; 19 | array[minIndex] = temp; 20 | } 21 | return array; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Integer[] array = {5, 1, 85, 4, 7, 9, 0, 3, 1}; 26 | Arrays.stream(selectionSort(array)).forEach(System.out::println); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/data_structures/arrays/MergeSortedArray.java: -------------------------------------------------------------------------------- 1 | package data_structures.arrays; 2 | 3 | import java.util.Arrays; 4 | 5 | public class MergeSortedArray { 6 | 7 | public static int[] MargeTwoSortedArray(int[] array1, int[] array2) { 8 | final int[] mergedArray = new int[array1.length + array2.length]; 9 | int j = 0, k = 0; 10 | for (int i = 0; i < mergedArray.length; i++) { 11 | if (j != array1.length && (k == array2.length || array1[j] < array2[k])) { 12 | mergedArray[i] = array1[j]; 13 | j++; 14 | } else { 15 | mergedArray[i] = array2[k]; 16 | k++; 17 | } 18 | } 19 | return mergedArray; 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] arr = MargeTwoSortedArray(new int[]{1,1,8,9,10}, new int[]{1,2,8,9,11,15,16}); 24 | Arrays.stream(arr).forEach(System.out::println); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/data_structures/arrays/MyArray.java: -------------------------------------------------------------------------------- 1 | package data_structures.arrays; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | 6 | /** 7 | * This is an example of how to right the same code in the course, 8 | * this is NOT an example of dynamic array in java, for dynamic arrays in java please see {@link ArrayList} 9 | */ 10 | public class MyArray { 11 | 12 | private Object[] data; 13 | private int capacity; 14 | private int length; 15 | 16 | public MyArray () { 17 | capacity = 1; 18 | length = 0; 19 | data = new Object[1]; 20 | } 21 | 22 | public Object get(int index) { 23 | return data[index]; 24 | } 25 | 26 | public void push(Object obj) { 27 | if(capacity == length) { 28 | data = Arrays.copyOf(data, capacity * 2); 29 | capacity *= 2; 30 | } 31 | data[length] = obj; 32 | length++; 33 | } 34 | 35 | public Object pop() { 36 | Object popped = data[length - 1]; 37 | data[length - 1] = null; 38 | length--; 39 | return popped; 40 | } 41 | 42 | public Object delete(int index) { 43 | Object itemToDelete = data[index]; 44 | shiftItems(index); 45 | return itemToDelete; 46 | } 47 | 48 | public void shiftItems(int index) { 49 | for (int i = index; i < length - 1; i++) { 50 | data[i] = data[i + 1]; 51 | } 52 | data[length - 1] = null; 53 | length--; 54 | } 55 | 56 | public static void main(String[] args) { 57 | MyArray m = new MyArray(); 58 | m.push("Hello"); 59 | m.push("World"); 60 | 61 | for (int i = 0; i < m.length; i++) { 62 | System.out.println(m.get(i)); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/data_structures/arrays/ReverseString.java: -------------------------------------------------------------------------------- 1 | package data_structures.arrays; 2 | 3 | public class ReverseString { 4 | 5 | public static String ReverseString(String string) { 6 | String result = ""; //It's more recommended to use "StringBuilder" object when manipulating strings 7 | final int length = string.length(); 8 | for (int i = length - 1; i >= 0; i--) { 9 | result += string.charAt(i); 10 | } 11 | return result; 12 | } 13 | 14 | public static String ReverseStringWithReelJava(String string) { 15 | return new StringBuilder(string).reverse().toString(); 16 | } 17 | 18 | public static String recursiveReversal (String str) { 19 | if (str.length() == 0) //breakpoint for recursion 20 | return ""; 21 | return recursiveReversal(str.substring(1)) + str.charAt(0); 22 | } 23 | 24 | public static void main(String[] args) { 25 | System.out.println(ReverseString("123456")); 26 | System.out.println(ReverseStringWithReelJava("123456")); 27 | System.out.println(recursiveReversal("123456")); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/data_structures/graphs/MyGraph.java: -------------------------------------------------------------------------------- 1 | package data_structures.graphs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | public class MyGraph { 9 | 10 | private HashMap> adjacentList; 11 | private int numberOfNodes; 12 | public MyGraph() { 13 | adjacentList = new HashMap<>(); 14 | numberOfNodes = 0; 15 | } 16 | 17 | public void addNode(int value) { 18 | adjacentList.put(value, new ArrayList<>()); 19 | numberOfNodes++; 20 | } 21 | 22 | public void addEdge(int value1, int value2) { 23 | adjacentList.get(value1).add(value2); 24 | adjacentList.get(value2).add(value1); 25 | } 26 | 27 | public void showConnections() { 28 | Set keys = adjacentList.keySet(); 29 | for (int node : keys) { 30 | List nodeConnections = adjacentList.get(node); 31 | StringBuilder connections = new StringBuilder(); 32 | for (int edge : nodeConnections) { 33 | connections.append(edge).append(" "); 34 | } 35 | System.out.println(node + "-->" + connections); 36 | } 37 | } 38 | 39 | public int getNumberOfNodes() { 40 | return numberOfNodes; 41 | } 42 | 43 | public static void main(String[] args) { 44 | MyGraph graph = new MyGraph(); 45 | graph.addNode(0); 46 | graph.addNode(1); 47 | graph.addNode(2); 48 | graph.addNode(3); 49 | graph.addNode(4); 50 | graph.addNode(5); 51 | graph.addNode(6); 52 | graph.addEdge(3, 1); 53 | graph.addEdge(3, 4); 54 | graph.addEdge(4, 2); 55 | graph.addEdge(4, 5); 56 | graph.addEdge(1, 2); 57 | graph.addEdge(1, 0); 58 | graph.addEdge(0, 2); 59 | graph.addEdge(6, 5); 60 | graph.showConnections(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/data_structures/hash_tables/FirstRecurringCharacter.java: -------------------------------------------------------------------------------- 1 | package data_structures.hash_tables; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | 6 | public class FirstRecurringCharacter { 7 | 8 | public static Object getFirstRecurringObject(Object[] inputArray) { 9 | for (int i = 0; i < inputArray.length; i++) { 10 | for (int j = i + 1; j < inputArray.length; j++) { 11 | if(inputArray[i].equals(inputArray[j])) { 12 | return inputArray[i]; 13 | } 14 | } 15 | } 16 | return null; 17 | } 18 | 19 | public static Object getFirstRecurringObjectBetter(Object[] inputArray) { 20 | HashSet map = new HashSet<>(); 21 | for (Object obj : inputArray) { 22 | if(map.contains(obj)) { 23 | return obj; 24 | } else { 25 | map.add(obj); 26 | } 27 | } 28 | return null; 29 | } 30 | 31 | public static Object getFirstRecurringObjectBetter2(Object[] inputArray) { 32 | HashSet map = new HashSet<>(Arrays.asList(inputArray)); //Filling the hash table before checking if the item exist 33 | for (Object obj : inputArray) { 34 | if (map.contains(obj)) { 35 | return obj; 36 | } 37 | } 38 | return null; 39 | } 40 | 41 | public static void main(String[] args) { 42 | Object[] arr = {1,5,8,5,1,8,8,7,4,4,10}; 43 | System.out.println(getFirstRecurringObjectBetter(arr)); 44 | System.out.println(getFirstRecurringObjectBetter2(arr)); 45 | System.out.println(getFirstRecurringObject(arr)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/data_structures/hash_tables/MyHashTable.java: -------------------------------------------------------------------------------- 1 | package data_structures.hash_tables; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * This is just an example on how you could write a HashTable as it was shown on the course, 9 | * this is not how it's implemented in Java, please refer to {@link java.util.HashMap} 10 | */ 11 | public class MyHashTable { 12 | 13 | private static class MyNodes extends ArrayList { 14 | } 15 | 16 | private final int length; 17 | private MyNodes[] data; 18 | 19 | public MyHashTable(int size) { 20 | length = size; 21 | data = new MyNodes[length]; 22 | } 23 | 24 | public void set(String key, int value) { 25 | if (data[hash(key)] == null) { 26 | data[hash(key)] = new MyNodes(); 27 | } 28 | data[hash(key)].add(new MyNode(key, value)); 29 | } 30 | 31 | public int get(String key) { 32 | if (data[hash(key)] == null) { 33 | return 0; 34 | } 35 | for (MyNode node : data[hash(key)]) { 36 | if (node.getKey().equals(key)) { 37 | return node.getValue(); 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | public List keys() { 44 | List keys = new ArrayList<>(); 45 | for (int i = 0; i < length; i++) { 46 | if (data[i] != null) { 47 | for (int j = 0; j < data[i].size(); j++) { 48 | keys.add(data[i].get(j).getKey()); 49 | } 50 | } 51 | } 52 | return keys; 53 | } 54 | 55 | private int hash(String key) { 56 | int hash = 0; 57 | for (int i = 0; i < key.length(); i++) { 58 | hash = (hash + key.charAt(i) * i) % length; 59 | } 60 | return hash; 61 | } 62 | 63 | public static void main(String[] args) { 64 | MyHashTable table = new MyHashTable(50); 65 | table.set("ta", 1000); 66 | table.set("tu", 589); 67 | table.set("e", 10); 68 | System.out.println(table.keys().size()); 69 | System.out.println(table.get("ta")); 70 | System.out.println(table.get("tu")); 71 | System.out.println(table.get("e")); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/data_structures/hash_tables/MyNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.hash_tables; 2 | 3 | public class MyNode { 4 | private String key; 5 | private int value; 6 | 7 | 8 | public MyNode(String key, int value) { 9 | this.key = key; 10 | this.value = value; 11 | } 12 | 13 | public String getKey() { 14 | return key; 15 | } 16 | 17 | public void setKey(String key) { 18 | this.key = key; 19 | } 20 | 21 | public int getValue() { 22 | return value; 23 | } 24 | 25 | public void setValue(int value) { 26 | this.value = value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/data_structures/linked_lists/doubly/MyDoublyLinkedList.java: -------------------------------------------------------------------------------- 1 | package data_structures.linked_lists.doubly; 2 | 3 | public class MyDoublyLinkedList { 4 | private MyDoublyLinkedNode head; 5 | private MyDoublyLinkedNode tail; 6 | private int length; 7 | 8 | public MyDoublyLinkedList(int value) { 9 | head = new MyDoublyLinkedNode(value); 10 | tail = head; 11 | length = 1; 12 | } 13 | 14 | public void prepend(int value) { 15 | MyDoublyLinkedNode newNode = new MyDoublyLinkedNode(value, null, head); 16 | head.setPrevious(newNode); 17 | head = newNode; 18 | length ++; 19 | } 20 | 21 | public void append(int value) { 22 | MyDoublyLinkedNode newNode = new MyDoublyLinkedNode(value, tail, null); 23 | tail.setNext(newNode); 24 | tail = newNode; 25 | length ++; 26 | } 27 | 28 | public void printList() { 29 | MyDoublyLinkedNode currentNode = head; 30 | System.out.print(currentNode.getValue()); 31 | currentNode = currentNode.getNext(); 32 | while (currentNode != null) { 33 | System.out.print("-->" + currentNode.getValue()); 34 | currentNode = currentNode.getNext(); 35 | } 36 | System.out.println(); 37 | } 38 | 39 | public void insert(int index, int value) { 40 | index = wrapIndex(index); 41 | if (index == 0) { 42 | prepend(value); 43 | return; 44 | } 45 | 46 | if (index == length - 1) { 47 | append(value); 48 | return; 49 | } 50 | 51 | MyDoublyLinkedNode leader = traverseToIndex(index - 1); 52 | MyDoublyLinkedNode follower = leader.getNext(); 53 | 54 | MyDoublyLinkedNode newNode = new MyDoublyLinkedNode(value, leader, follower); 55 | leader.setNext(newNode); 56 | follower.setPrevious(newNode); 57 | length++; 58 | } 59 | 60 | public void remove(int index) { 61 | index = wrapIndex(index); 62 | if(index == 0) { 63 | head = head.getNext(); 64 | head.setPrevious(null); 65 | length--; 66 | return; 67 | } 68 | 69 | MyDoublyLinkedNode leader = traverseToIndex(index - 1); 70 | MyDoublyLinkedNode nodeToRemove = leader.getNext(); 71 | leader.setNext(nodeToRemove.getNext()); 72 | nodeToRemove.getNext().setPrevious(leader); 73 | length--; 74 | } 75 | 76 | public MyDoublyLinkedNode traverseToIndex(int index) { 77 | index = wrapIndex(index); 78 | MyDoublyLinkedNode currentNode = head; 79 | for (int i = 0; i < index; i++) { 80 | currentNode = currentNode.getNext(); 81 | } 82 | return currentNode; 83 | } 84 | 85 | private int wrapIndex(int index) { //Used for wrapping the given index to make sure it's valid 86 | return Math.max(Math.min(index, length - 1), 0); 87 | } 88 | 89 | public MyDoublyLinkedNode getHead() { 90 | return head; 91 | } 92 | 93 | public MyDoublyLinkedNode getTail() { 94 | return tail; 95 | } 96 | 97 | public int getLength() { 98 | return length; 99 | } 100 | 101 | public static void main(String[] args) { 102 | MyDoublyLinkedList mySinglyLinkedList = new MyDoublyLinkedList(5); 103 | mySinglyLinkedList.append(7); 104 | mySinglyLinkedList.append(4); 105 | mySinglyLinkedList.prepend(10); 106 | mySinglyLinkedList.printList(); 107 | mySinglyLinkedList.insert(2,15); 108 | mySinglyLinkedList.printList(); 109 | mySinglyLinkedList.remove(0); 110 | mySinglyLinkedList.printList(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/data_structures/linked_lists/doubly/MyDoublyLinkedNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.linked_lists.doubly; 2 | 3 | public class MyDoublyLinkedNode { 4 | 5 | private int value; 6 | private MyDoublyLinkedNode previous; 7 | private MyDoublyLinkedNode next; 8 | 9 | public MyDoublyLinkedNode(int value) { 10 | this.value = value; 11 | this.next = null; 12 | } 13 | 14 | public MyDoublyLinkedNode(int value, MyDoublyLinkedNode previous, MyDoublyLinkedNode next) { 15 | this.value = value; 16 | this.next = next; 17 | this.previous = previous; 18 | } 19 | 20 | public int getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(int value) { 25 | this.value = value; 26 | } 27 | 28 | public MyDoublyLinkedNode getNext() { 29 | return next; 30 | } 31 | 32 | public void setNext(MyDoublyLinkedNode next) { 33 | this.next = next; 34 | } 35 | 36 | public MyDoublyLinkedNode getPrevious() { 37 | return previous; 38 | } 39 | 40 | public void setPrevious(MyDoublyLinkedNode previous) { 41 | this.previous = previous; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/data_structures/linked_lists/singly/MySinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | package data_structures.linked_lists.singly; 2 | 3 | public class MySinglyLinkedList { 4 | private MySinglyLinkedNode head; 5 | private MySinglyLinkedNode tail; 6 | private int length; 7 | 8 | public MySinglyLinkedList(int value) { 9 | head = new MySinglyLinkedNode(value); 10 | tail = head; 11 | length = 1; 12 | } 13 | 14 | public void prepend(int value) { 15 | head = new MySinglyLinkedNode(value, head); 16 | length ++; 17 | } 18 | 19 | public void append(int value) { 20 | MySinglyLinkedNode newNode = new MySinglyLinkedNode(value); 21 | tail.setNext(newNode); 22 | tail = newNode; 23 | length ++; 24 | } 25 | 26 | public void printList() { 27 | if(head == null) { 28 | return; 29 | } 30 | MySinglyLinkedNode currentNode = head; 31 | System.out.print(currentNode.getValue()); 32 | currentNode = currentNode.getNext(); 33 | while (currentNode != null) { 34 | System.out.print("-->" + currentNode.getValue()); 35 | currentNode = currentNode.getNext(); 36 | } 37 | System.out.println(); 38 | } 39 | 40 | public void insert(int index, int value) { 41 | index = wrapIndex(index); 42 | if (index == 0) { 43 | prepend(value); 44 | return; 45 | } 46 | 47 | if (index == length - 1) { 48 | append(value); 49 | return; 50 | } 51 | 52 | MySinglyLinkedNode leader = traverseToIndex(index - 1); 53 | MySinglyLinkedNode nextNode = leader.getNext(); 54 | 55 | MySinglyLinkedNode newNode = new MySinglyLinkedNode(value, nextNode); 56 | leader.setNext(newNode); 57 | length++; 58 | } 59 | 60 | public void remove(int index) { 61 | index = wrapIndex(index); 62 | if(index == 0) { 63 | head = head.getNext(); 64 | length--; 65 | return; 66 | } 67 | 68 | MySinglyLinkedNode leader = traverseToIndex(index - 1); 69 | MySinglyLinkedNode nodeToRemove = leader.getNext(); 70 | leader.setNext(nodeToRemove.getNext()); 71 | length--; 72 | } 73 | 74 | public void reverse() { 75 | MySinglyLinkedNode first = head; 76 | tail = head; 77 | MySinglyLinkedNode second = first.getNext(); 78 | for (int i = 0; i < length - 1; i++) { 79 | MySinglyLinkedNode temp = second.getNext(); 80 | second.setNext(first); 81 | first = second; 82 | second = temp; 83 | } 84 | head.setNext(null); 85 | head = first; 86 | } 87 | 88 | public MySinglyLinkedNode traverseToIndex(int index) { 89 | index = wrapIndex(index); 90 | MySinglyLinkedNode currentNode = head; 91 | for (int i = 0; i < index; i++) { 92 | currentNode = currentNode.getNext(); 93 | } 94 | return currentNode; 95 | } 96 | 97 | private int wrapIndex(int index) { //Used for wrapping the given index to make sure it's valid 98 | return Math.max(Math.min(index, length - 1), 0); 99 | } 100 | 101 | public MySinglyLinkedNode getHead() { 102 | return head; 103 | } 104 | 105 | public MySinglyLinkedNode getTail() { 106 | return tail; 107 | } 108 | 109 | public int getLength() { 110 | return length; 111 | } 112 | 113 | public static void main(String[] args) { 114 | MySinglyLinkedList mySinglyLinkedList = new MySinglyLinkedList(5); 115 | mySinglyLinkedList.append(8); 116 | mySinglyLinkedList.append(4); 117 | mySinglyLinkedList.prepend(10); 118 | mySinglyLinkedList.printList(); 119 | mySinglyLinkedList.insert(2,15); 120 | mySinglyLinkedList.printList(); 121 | mySinglyLinkedList.remove(100); 122 | mySinglyLinkedList.remove(2); 123 | mySinglyLinkedList.printList(); 124 | mySinglyLinkedList.reverse(); 125 | mySinglyLinkedList.printList(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/data_structures/linked_lists/singly/MySinglyLinkedNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.linked_lists.singly; 2 | 3 | public class MySinglyLinkedNode { 4 | 5 | private int value; 6 | private MySinglyLinkedNode next; 7 | 8 | public MySinglyLinkedNode(int value) { 9 | this.value = value; 10 | this.next = null; 11 | } 12 | 13 | public MySinglyLinkedNode(int value, MySinglyLinkedNode next) { 14 | this.value = value; 15 | this.next = next; 16 | } 17 | 18 | public int getValue() { 19 | return value; 20 | } 21 | 22 | public void setValue(int value) { 23 | this.value = value; 24 | } 25 | 26 | public MySinglyLinkedNode getNext() { 27 | return next; 28 | } 29 | 30 | public void setNext(MySinglyLinkedNode next) { 31 | this.next = next; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/data_structures/queues/using_linked_list/MyQueue.java: -------------------------------------------------------------------------------- 1 | package data_structures.queues.using_linked_list; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | public class MyQueue { 6 | 7 | private MySinglyLinkedNode first; 8 | private MySinglyLinkedNode last; 9 | private int length; 10 | 11 | public MyQueue() { 12 | first = null; 13 | last = null; 14 | length = 0; 15 | } 16 | 17 | public int peek() { 18 | if(first == null) { 19 | throw new NoSuchElementException(); 20 | } 21 | return first.getValue(); 22 | } 23 | 24 | public void enqueue(int value) { 25 | MySinglyLinkedNode newNode = new MySinglyLinkedNode(value); 26 | if(length == 0) { 27 | first = newNode; 28 | } 29 | else { 30 | last.setNext(newNode); 31 | } 32 | last = newNode; 33 | length++; 34 | } 35 | 36 | public void dequeue() { 37 | if(first == null) { 38 | throw new NoSuchElementException(); 39 | } 40 | first = first.getNext(); 41 | length--; 42 | if(length == 0) { 43 | last = null; 44 | } 45 | } 46 | 47 | public void printQueue() { 48 | if(first == null) { 49 | return; 50 | } 51 | MySinglyLinkedNode currentNode = first; 52 | System.out.print(currentNode.getValue()); 53 | currentNode = currentNode.getNext(); 54 | while (currentNode != null) { 55 | System.out.print("-->" + currentNode.getValue()); 56 | currentNode = currentNode.getNext(); 57 | } 58 | System.out.println(); 59 | } 60 | 61 | public static void main(String[] args) { 62 | MyQueue queue = new MyQueue(); 63 | queue.enqueue(3); 64 | queue.enqueue(5); 65 | queue.enqueue(5); 66 | queue.printQueue(); 67 | queue.dequeue(); 68 | queue.printQueue(); 69 | queue.dequeue(); 70 | queue.dequeue(); 71 | queue.printQueue(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/data_structures/queues/using_linked_list/MySinglyLinkedNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.queues.using_linked_list; 2 | 3 | public class MySinglyLinkedNode { 4 | 5 | private int value; 6 | private MySinglyLinkedNode next; 7 | 8 | public MySinglyLinkedNode(int value) { 9 | this.value = value; 10 | this.next = null; 11 | } 12 | 13 | public MySinglyLinkedNode(int value, MySinglyLinkedNode next) { 14 | this.value = value; 15 | this.next = next; 16 | } 17 | 18 | public int getValue() { 19 | return value; 20 | } 21 | 22 | public void setValue(int value) { 23 | this.value = value; 24 | } 25 | 26 | public MySinglyLinkedNode getNext() { 27 | return next; 28 | } 29 | 30 | public void setNext(MySinglyLinkedNode next) { 31 | this.next = next; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/data_structures/queues/using_stack/MyQueue.java: -------------------------------------------------------------------------------- 1 | package data_structures.queues.using_stack; 2 | 3 | import java.util.Stack; 4 | 5 | public class MyQueue { 6 | private Stack stack = new Stack<>(); 7 | private Stack auxiliaryStack = new Stack<>(); 8 | 9 | public void enqueue(int value) { 10 | stack.push(value); 11 | } 12 | 13 | public int dequeue() { 14 | fillAuxiliaryStackWithStack(); 15 | int value = auxiliaryStack.pop(); 16 | fillStackWithAuxiliaryStack(); 17 | return value; 18 | } 19 | 20 | public int peek() { 21 | fillAuxiliaryStackWithStack(); 22 | int value = auxiliaryStack.peek(); 23 | fillStackWithAuxiliaryStack(); 24 | return value; 25 | } 26 | 27 | public void printQueue() { 28 | if (stack.empty()) { 29 | return; 30 | } 31 | 32 | fillAuxiliaryStackWithStack(); 33 | Object[] list = auxiliaryStack.toArray(); 34 | for (Object o : list) { 35 | System.out.print("-->" + o); 36 | } 37 | System.out.println(); 38 | fillStackWithAuxiliaryStack(); 39 | } 40 | 41 | private void fillAuxiliaryStackWithStack() { 42 | while (!stack.isEmpty()) { //Making the "auxiliaryStack" stack as queue of "Stack" 43 | auxiliaryStack.push(stack.pop()); 44 | } 45 | } 46 | 47 | private void fillStackWithAuxiliaryStack() { 48 | while (!auxiliaryStack.isEmpty()) { //Return stack to the original state 49 | stack.push(auxiliaryStack.pop()); 50 | } 51 | } 52 | 53 | 54 | public static void main(String[] args) { 55 | MyQueue queue = new MyQueue(); 56 | queue.enqueue(10); 57 | queue.enqueue(4); 58 | queue.enqueue(5); 59 | queue.printQueue(); 60 | queue.dequeue(); 61 | queue.printQueue(); 62 | queue.dequeue(); 63 | queue.printQueue(); 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/data_structures/stacks/using_array/MyStack.java: -------------------------------------------------------------------------------- 1 | package data_structures.stacks.using_array; 2 | 3 | import java.util.ArrayList; 4 | import java.util.EmptyStackException; 5 | import java.util.List; 6 | 7 | public class MyStack { 8 | private List array = new ArrayList<>(); 9 | 10 | public MyStack() { 11 | } 12 | 13 | public int peak() { 14 | if(array.size() == 0) { 15 | throw new EmptyStackException(); 16 | } 17 | return array.get(this.array.size() - 1); 18 | } 19 | 20 | public int pop() { 21 | if(array.size() == 0) { 22 | throw new EmptyStackException(); 23 | } 24 | return array.remove(array.size() - 1); 25 | } 26 | 27 | public void push(int valueToPush) { 28 | array.add(valueToPush); 29 | } 30 | 31 | public void printStack() { 32 | for (int value : array) { 33 | System.out.println(value); 34 | } 35 | } 36 | 37 | public static void main(String[] args) { 38 | MyStack stack = new MyStack(); 39 | stack.push(5); 40 | stack.printStack(); 41 | stack.push(3); 42 | stack.printStack(); 43 | stack.pop(); 44 | stack.printStack(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/data_structures/stacks/using_linked_list/MySinglyLinkedNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.stacks.using_linked_list; 2 | 3 | public class MySinglyLinkedNode { 4 | 5 | private int value; 6 | private MySinglyLinkedNode next; 7 | 8 | public MySinglyLinkedNode(int value) { 9 | this.value = value; 10 | this.next = null; 11 | } 12 | 13 | public MySinglyLinkedNode(int value, MySinglyLinkedNode next) { 14 | this.value = value; 15 | this.next = next; 16 | } 17 | 18 | public int getValue() { 19 | return value; 20 | } 21 | 22 | public void setValue(int value) { 23 | this.value = value; 24 | } 25 | 26 | public MySinglyLinkedNode getNext() { 27 | return next; 28 | } 29 | 30 | public void setNext(MySinglyLinkedNode next) { 31 | this.next = next; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/data_structures/stacks/using_linked_list/MyStack.java: -------------------------------------------------------------------------------- 1 | package data_structures.stacks.using_linked_list; 2 | 3 | import java.util.EmptyStackException; 4 | 5 | public class MyStack { 6 | private MySinglyLinkedNode top; 7 | private MySinglyLinkedNode bottom; 8 | private int length; 9 | 10 | public MyStack() { 11 | top = null; 12 | bottom = null; 13 | length = 0; 14 | } 15 | 16 | public int peak() { 17 | if(length == 0) { 18 | throw new EmptyStackException(); 19 | } 20 | return top.getValue(); 21 | } 22 | 23 | public int pop() { 24 | if(length == 0) { 25 | throw new EmptyStackException(); 26 | } 27 | MySinglyLinkedNode tempTop = top; 28 | top = top.getNext(); 29 | length--; 30 | if(length == 0) { 31 | bottom = null; 32 | } 33 | return tempTop.getValue(); 34 | } 35 | 36 | public void push(int valueToPush) { 37 | top = new MySinglyLinkedNode(valueToPush, top); 38 | if(length == 0) { 39 | bottom = top; 40 | } 41 | length++; 42 | } 43 | 44 | public void printStack() { 45 | if(top == null) { 46 | return; 47 | } 48 | MySinglyLinkedNode currentNode = top; 49 | System.out.print(currentNode.getValue()); 50 | currentNode = currentNode.getNext(); 51 | while (currentNode != null) { 52 | System.out.print("-->" + currentNode.getValue()); 53 | currentNode = currentNode.getNext(); 54 | } 55 | System.out.println(); 56 | } 57 | 58 | public static void main(String[] args) { 59 | MyStack stack = new MyStack(); 60 | stack.push(5); 61 | stack.printStack(); 62 | stack.push(3); 63 | stack.printStack(); 64 | stack.pop(); 65 | stack.pop(); 66 | stack.printStack(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/data_structures/trees/binary_search_tree/MyBinaryNode.java: -------------------------------------------------------------------------------- 1 | package data_structures.trees.binary_search_tree; 2 | 3 | public class MyBinaryNode { 4 | 5 | private int value; 6 | private MyBinaryNode left; 7 | private MyBinaryNode right; 8 | 9 | 10 | public MyBinaryNode(int value, MyBinaryNode left, MyBinaryNode right) { 11 | this.value = value; 12 | this.left = left; 13 | this.right = right; 14 | } 15 | 16 | public MyBinaryNode (int value) { 17 | this.value = value; 18 | this.left = null; 19 | this.right = null; 20 | } 21 | 22 | public MyBinaryNode getLeft() { 23 | return left; 24 | } 25 | 26 | public void setLeft(MyBinaryNode left) { 27 | this.left = left; 28 | } 29 | 30 | public MyBinaryNode getRight() { 31 | return right; 32 | } 33 | 34 | public void setRight(MyBinaryNode right) { 35 | this.right = right; 36 | } 37 | 38 | public int getValue() { 39 | return value; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/data_structures/trees/binary_search_tree/MyBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package data_structures.trees.binary_search_tree; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | public class MyBinarySearchTree { 9 | 10 | enum SearchType { 11 | IN_ORDER, 12 | PRE_ORDER, 13 | POST_ORDER 14 | } 15 | 16 | private MyBinaryNode root; 17 | 18 | public MyBinarySearchTree() { 19 | root = null; 20 | } 21 | 22 | public void insert(int value) { 23 | if(root == null) { 24 | root = new MyBinaryNode(value); 25 | return; 26 | } 27 | MyBinaryNode currentNode = root; 28 | while (true) { 29 | if (currentNode.getValue() > value) { 30 | if(currentNode.getLeft() == null) { 31 | currentNode.setLeft(new MyBinaryNode(value)); 32 | return; 33 | } 34 | currentNode = currentNode.getLeft(); 35 | } else { 36 | if(currentNode.getRight() == null) { 37 | currentNode.setRight(new MyBinaryNode(value)); 38 | return; 39 | } 40 | currentNode = currentNode.getRight(); 41 | } 42 | } 43 | } 44 | 45 | public MyBinaryNode lookup(int value) { 46 | if(root == null) { 47 | return null; 48 | } 49 | MyBinaryNode currentNode = root; 50 | while (currentNode != null) { 51 | if(value < currentNode.getValue()) { 52 | currentNode = currentNode.getLeft(); 53 | } else if(value > currentNode.getValue()) { 54 | currentNode = currentNode.getRight(); 55 | } else { 56 | return currentNode; 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | public void remove(int value) { 63 | if (root == null) { 64 | return; 65 | } 66 | 67 | MyBinaryNode nodeToRemove = root; 68 | MyBinaryNode parentNode = null; 69 | while (nodeToRemove.getValue() != value) { //Searching for the node to remove and it's parent 70 | parentNode = nodeToRemove; 71 | if (value < nodeToRemove.getValue()) { 72 | nodeToRemove = nodeToRemove.getLeft(); 73 | } else if (value > nodeToRemove.getValue()) { 74 | nodeToRemove = nodeToRemove.getRight(); 75 | } 76 | } 77 | 78 | MyBinaryNode replacementNode = null; 79 | if (nodeToRemove.getRight() != null) { //We have a right node 80 | replacementNode = nodeToRemove.getRight(); 81 | if(replacementNode.getLeft() == null) { //We don't have a left node 82 | replacementNode.setLeft(nodeToRemove.getLeft()); 83 | } else { //We have a have a left node, lets find the leftmost 84 | MyBinaryNode replacementParentNode = nodeToRemove; 85 | while (replacementNode.getLeft() != null) { 86 | replacementParentNode = replacementNode; 87 | replacementNode = replacementNode.getLeft(); 88 | } 89 | replacementParentNode.setLeft(null); 90 | replacementNode.setLeft(nodeToRemove.getLeft()); 91 | replacementNode.setRight(nodeToRemove.getRight()); 92 | } 93 | } else if(nodeToRemove.getLeft() != null) {//We only have a left node 94 | replacementNode = nodeToRemove.getLeft(); 95 | } 96 | 97 | if(parentNode == null) { 98 | root = replacementNode; 99 | } else if(parentNode.getLeft() == nodeToRemove) { //We are a left child 100 | parentNode.setLeft(replacementNode); 101 | } else { //We are a right child 102 | parentNode.setRight(replacementNode); 103 | } 104 | } 105 | 106 | int count = 0; 107 | public void printTree() { 108 | count = 0; 109 | printTree(root); 110 | } 111 | 112 | public List breathFirstSearchIteratively() { 113 | MyBinaryNode currentNode = root; 114 | List list = new ArrayList<>(); 115 | Queue queue = new LinkedList<>(); 116 | queue.add(currentNode); 117 | 118 | while (!queue.isEmpty()) { 119 | currentNode = queue.poll(); 120 | list.add(currentNode.getValue()); 121 | if(currentNode.getLeft() != null) { 122 | queue.add(currentNode.getLeft()); 123 | } 124 | 125 | if(currentNode.getRight() != null) { 126 | queue.add(currentNode.getRight()); 127 | } 128 | } 129 | return list; 130 | } 131 | 132 | public List breathFirstSearchRecursively() { 133 | Queue queue = new LinkedList<>(); 134 | queue.add(root); 135 | return breathFirstSearchRecursively(queue, new ArrayList<>()); 136 | } 137 | 138 | public List depthFirstSearchInOder(SearchType searchType) { 139 | return depthFirstSearchInOder(root, new ArrayList<>(), searchType); 140 | } 141 | 142 | private List depthFirstSearchInOder(MyBinaryNode node, ArrayList list, SearchType searchType) { 143 | if(searchType == SearchType.PRE_ORDER) 144 | list.add(node.getValue()); 145 | if(node.getLeft() != null) { 146 | depthFirstSearchInOder(node.getLeft(), list, searchType); 147 | } 148 | if(searchType == SearchType.IN_ORDER) 149 | list.add(node.getValue()); 150 | if(node.getRight() != null) { 151 | depthFirstSearchInOder(node.getRight(), list, searchType); 152 | } 153 | if(searchType == SearchType.POST_ORDER) 154 | list.add(node.getValue()); 155 | return list; 156 | } 157 | 158 | private List breathFirstSearchRecursively(Queue queue, List list) { 159 | if (queue.isEmpty()) { 160 | return list; 161 | } 162 | MyBinaryNode currentNode = queue.poll(); 163 | list.add(currentNode.getValue()); 164 | if (currentNode.getLeft() != null) { 165 | queue.add(currentNode.getLeft()); 166 | } 167 | 168 | if (currentNode.getRight() != null) { 169 | queue.add(currentNode.getRight()); 170 | } 171 | return breathFirstSearchRecursively(queue, list); 172 | } 173 | 174 | 175 | private void printTree(MyBinaryNode node) { 176 | System.out.print(node.getValue()); 177 | System.out.println(); 178 | count++; 179 | if(node.getLeft() != null) { 180 | System.out.print("\t".repeat(Math.max(0, count)) + "Left: "); 181 | printTree(node.getLeft()); 182 | } 183 | if(node.getRight() != null) { 184 | System.out.print("\t".repeat(Math.max(0, count)) +"Right: "); 185 | printTree(node.getRight()); 186 | } 187 | count--; 188 | } 189 | 190 | public static void main(String[] args) { 191 | MyBinarySearchTree tree = new MyBinarySearchTree(); 192 | tree.insert(9); 193 | tree.insert(4); 194 | tree.insert(20); 195 | tree.insert(1); 196 | tree.insert(6); 197 | tree.insert(15); 198 | tree.insert(170); 199 | tree.printTree(); 200 | tree.remove(20); 201 | tree.remove(4); 202 | tree.printTree(); 203 | tree.insert(20); 204 | tree.insert(18); 205 | tree.insert(10); 206 | tree.printTree(); 207 | tree.remove(170); 208 | tree.printTree(); 209 | System.out.println("Breath first search " + tree.breathFirstSearchIteratively()); 210 | System.out.println("Depth first search - in order " + tree.depthFirstSearchInOder(SearchType.IN_ORDER)); 211 | System.out.println("Depth first search - pre order " + tree.depthFirstSearchInOder(SearchType.PRE_ORDER)); 212 | System.out.println("Depth first search - post order " + tree.depthFirstSearchInOder(SearchType.POST_ORDER)); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/dynamic_programming/DynamicFibonacci.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming; 2 | 3 | import java.util.HashMap; 4 | 5 | public class DynamicFibonacci { 6 | 7 | private static final HashMap cache = new HashMap<>(); 8 | public static int fibonacciMaster(int n) { 9 | if(cache.containsKey(n)) { 10 | return cache.get(n); 11 | } 12 | if(n < 2){ 13 | return n; 14 | } 15 | cache.put(n, fibonacciMaster(n - 1) + fibonacciMaster(n - 2)); 16 | return cache.get(n); 17 | } 18 | 19 | public static void main(String[] args) { 20 | System.out.println(fibonacciMaster(1000)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/interview_question/CommonItems.java: -------------------------------------------------------------------------------- 1 | package interview_question; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.Objects; 7 | import java.util.Random; 8 | import java.util.stream.Stream; 9 | 10 | public class CommonItems { 11 | /* Given 2 arrays, create a function that let's a user know (true/false) whether these two arrays contain any common items 12 | For Example: 13 | const array1 = ['a', 'b', 'c', 'x']; 14 | const array2 = ['z', 'y', 'i']; 15 | should return false. 16 | ----------- 17 | const array1 = ['a', 'b', 'c', 'x']; 18 | const array2 = ['z', 'y', 'x']; 19 | should return true. 20 | 2 parameters - arrays - no size limit 21 | return true or false 22 | */ 23 | 24 | private static Object[] array1 = {'a', "asd", '7', 'r', "null"}; 25 | private static Object[] array2 = {'z', new String("asd"), null, 'x'}; 26 | private static final boolean makeScalable = true; //For testing large scale time duration 27 | 28 | public static void main(String[] args) { 29 | if (makeScalable) { 30 | array1 = new Object[100000]; 31 | array2 = new Object[100000]; 32 | Random s = new Random(); 33 | for (int i = 0; i < array1.length; i++) { 34 | array1[i] = s.nextLong(); 35 | } 36 | 37 | for (int i = 0; i < array2.length; i++) { 38 | array2[i] = s.nextLong(); 39 | } 40 | } 41 | 42 | long startTime = System.nanoTime(); 43 | boolean result = containsCommonItemsBetter(array1, array2); 44 | long endTime = System.nanoTime(); 45 | System.out.format("Better solution result: %s with time of - %d%n", result, endTime - startTime); 46 | 47 | startTime = System.nanoTime(); 48 | result = containsCommonItemsBetterAndCleaner(array1, array2); 49 | endTime = System.nanoTime(); 50 | System.out.format("Better and cleaner solution result: %s with time of - %d%n", result, endTime - startTime); 51 | 52 | startTime = System.nanoTime(); 53 | result = containsCommonItems(array1, array2); 54 | endTime = System.nanoTime(); 55 | System.out.format("Bad solution result: %s with time of - %d%n", result, endTime - startTime); 56 | } 57 | 58 | /** 59 | * A "naive" approach for solving the question, with 60 | * time complexity of O(a * b) - exponential 61 | * space complexity of O(1) - constant. 62 | * Please note that we have to use {@link Objects#equals(Object, Object)} method so strings would work properly and we are using the 63 | * equals method in {@link Objects} class so we could accept null inputs without null exception 64 | * @param array1 - the first input array 65 | * @param array2 - the second input array 66 | * @return A boolean indicating whether those two arrays have any common items 67 | */ 68 | public static boolean containsCommonItems(Object[] array1, Object[] array2) { 69 | for (Object obj1 : array1) { 70 | for (Object obj2 : array2) { 71 | if (Objects.equals(obj1, obj2)) { 72 | return true; 73 | } 74 | } 75 | } 76 | return false; 77 | } 78 | 79 | /** 80 | * A better solution which includes the use of {@link HashSet}, here we are using {@link HashSet} 81 | * and NOT {@link HashMap} (key, value data structure) as it was demonstrated in the course as 82 | * there is no reason to store true for each key and we can check for common objects using the {@link HashSet#contains(Object)} method. 83 | * time complexity of O(b) - linear 84 | * space complexity of O(a) - linear 85 | * @param array1 - the first input array 86 | * @param array2 - the second input array 87 | * @return A boolean indicating whether those two arrays have any common items 88 | */ 89 | public static boolean containsCommonItemsBetter(Object[] array1, Object[] array2) { 90 | HashSet mapOfFirstArray = new HashSet<>(); 91 | for (Object obj1: array1) { 92 | mapOfFirstArray.add(obj1); 93 | } 94 | 95 | for (Object obj2 : array2) { 96 | if(mapOfFirstArray.contains(obj2)) { 97 | return true; 98 | } 99 | } 100 | return false; 101 | } 102 | 103 | /** 104 | * A better and cleaner solution which includes the use of {@link HashSet}, here we are using {@link HashSet} 105 | * and NOT {@link HashMap} (key, value data structure) as it was demonstrated in the course as 106 | * there is no reason to store true for each key and we can check for common objects using the {@link HashSet#contains(Object)} method. 107 | * This method also takes advantage of features added in Java SE8 ({@link Stream}) 108 | * time complexity of O(b) - linear 109 | * space complexity of O(a) - linear 110 | * @param array1 - the first input array 111 | * @param array2 - the second input array 112 | * @return A boolean indicating whether those two arrays have any common items 113 | */ 114 | public static boolean containsCommonItemsBetterAndCleaner(Object[] array1, Object[] array2) { 115 | HashSet mapOfFirstArray = new HashSet<>(Arrays.asList(array1)); 116 | return Stream.of(array2).anyMatch(mapOfFirstArray::contains); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/interview_question/amazon_interview_questions/ValidParentheses.java: -------------------------------------------------------------------------------- 1 | package interview_question.amazon_interview_questions; 2 | 3 | import java.util.HashMap; 4 | import java.util.Stack; 5 | 6 | public class ValidParentheses { 7 | static HashMap map = new HashMap<>(); 8 | public static boolean isValidParentheses(String string) { 9 | Stack chars = new Stack<>(); 10 | for (int i = 0; i < string.length(); i++) { 11 | if(!map.containsKey(string.charAt(i))) { 12 | if("{[(".contains(string.charAt(i) + "")) { 13 | chars.add(string.charAt(i)); 14 | } 15 | } else { 16 | char topElement = chars.empty() ? '#' : chars.pop(); 17 | if(!map.get(string.charAt(i)).equals(topElement)) { 18 | return false; 19 | } 20 | } 21 | } 22 | return chars.isEmpty(); 23 | } 24 | 25 | public static void main(String[] args) { 26 | map.put('}', '{'); 27 | map.put(']', '['); 28 | map.put(')', '('); 29 | String s = "{[1234]}{56}"; 30 | System.out.println(isValidParentheses(s)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/interview_question/facebook_interview_questions/NumberOfIslands.java: -------------------------------------------------------------------------------- 1 | package interview_question.facebook_interview_questions; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public class NumberOfIslands { 7 | 8 | public static int getNumberOfIslands(int[][] grid) { 9 | Set visited = new HashSet<>(); 10 | int count = 0; 11 | for (int i = 0; i < grid.length; i++) { 12 | for (int j = 0; j < grid[0].length; j++) { 13 | if (visited.contains(i + "" + j)) { 14 | continue; 15 | } 16 | if (grid[i][j] == 1) { //We found a new island, lets scout it and count it! 17 | scoutIsland(grid, i, j, visited); 18 | count++; 19 | } 20 | } 21 | } 22 | return count; 23 | } 24 | 25 | private static void scoutIsland(int[][] grid, int i, int j, Set visited) { 26 | if (visited.contains(i + "" + j) || i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0) { 27 | return; 28 | } 29 | visited.add(i + "" + j); 30 | scoutIsland(grid, i + 1, j, visited); //Scouting the island in all 4 directions 31 | scoutIsland(grid, i, j + 1, visited); 32 | scoutIsland(grid, i - 1, j, visited); 33 | scoutIsland(grid, i, j - 1, visited); 34 | } 35 | 36 | public static void main(String[] args) { 37 | int[][] grid = 38 | {{1, 1, 0, 1, 0}, 39 | {1, 1, 0, 1, 0}, 40 | {0, 0, 1, 0, 0}, 41 | {0, 0, 0, 1, 1}}; 42 | System.out.println(getNumberOfIslands(grid)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/interview_question/google_interview_questions/TrappingRainWater.java: -------------------------------------------------------------------------------- 1 | package interview_question.google_interview_questions; 2 | 3 | public class TrappingRainWater { 4 | 5 | /** 6 | * Not the most efficient solution but that what I came up with the first time. 7 | * This solution counts each level separately so its O(n * k) where n is the length of the list 8 | * and k is the number of levels 9 | */ 10 | public static int getTrappingRainWater(int[] height) { 11 | int max = 0; 12 | for (int i = 0; i < height.length; i++) { 13 | if(max < height[i]) { 14 | max = height[i]; 15 | } 16 | } 17 | int count = 0; 18 | for (int i = 1; i < max; i++) { 19 | count += countWaterAtLevel(height, i); 20 | } 21 | return count; 22 | } 23 | 24 | private static int countWaterAtLevel(int[] height, int level) { 25 | int first = 0; 26 | for (int i = 0; i < height.length; i++) { 27 | if(level <= height[i]) { 28 | first = i; 29 | break; 30 | } 31 | } 32 | 33 | int last = 0; 34 | for (int i = height.length - 1; i >= 0; i--) { 35 | if(level <= height[i]) { 36 | last = i; 37 | break; 38 | } 39 | } 40 | int count = 0; 41 | for (int i = first; i < last + 1; i++) { 42 | if(level > height[i]) { 43 | count++; 44 | } 45 | } 46 | return count; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] array = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; 51 | System.out.println(getTrappingRainWater(array)); 52 | } 53 | } 54 | --------------------------------------------------------------------------------