├── .gitignore ├── README.md ├── algorithms-with-java.iml └── src ├── advanced_exam_preparation ├── ChainLightning.java ├── RoadTrip.java └── TourDeSofia.java ├── combinatorial_problems ├── CombinationsWithRepetition.java ├── CombinationsWithoutRepetition.java ├── NChooseKCount.java ├── PermutationsWithRepetition.java ├── PermutationsWithoutRepetition.java ├── VariationsWithRepetition.java └── VariationsWithoutRepetition.java ├── dynamic_programming_advanced_exercise ├── AbaspaBasapa.java ├── RectangleIntersection.java ├── TheMadGardener.java └── ZigzagMatrix.java ├── dynamic_programming_advanced_lab ├── Knapsack.java └── LCS.java ├── dynamic_programming_exercise ├── BinomialCoefficients.java ├── ConnectingCables.java ├── DividingPresents.java ├── LongestZigZag.java ├── MinimumEditDistance.java ├── SumWithLimitedCoins.java ├── SumWithUnlimitedCoins.java └── WordDifferences.java ├── fundamentals_exam_preparation ├── ClusterBorder.java ├── Molecules.java └── MonkeyBusiness.java ├── graph_theory_traversal_and_shortest_paths ├── ConnectedComponents.java ├── ShortestPath.java └── TopologicalSort.java ├── graph_theory_traversal_and_shortest_paths_exercise ├── AreasInMatrix.java ├── BreakCycles.java ├── CyclesInGraph.java ├── DistanceBetween.java ├── RoadReconstruction.java ├── Salaries.java └── TheMatrix.java ├── graphs_bellmanFord_longest_path_in_dag_exercise ├── BigTrip.java ├── CableNetwork.java ├── CheapTownTour.java ├── ModifiedKruskal.java ├── MostReliablePath.java └── Undefined.java ├── graphs_bellmanFord_longest_path_in_dag_lab ├── BellmanFord.java └── LongestPath.java ├── graphs_dijkstraI_and_mst_lab ├── dijkstra │ ├── Dijkstra.java │ ├── Edge.java │ ├── KruskalAlgorithm.java │ └── Main.java └── mst │ ├── Dijkstra.java │ ├── Edge.java │ ├── KruskalAlgorithm.java │ └── Main.java ├── graphs_strongly_connected_components_max_flow_exercise ├── FindBiConnected.java └── MaximumTasks.java ├── graphs_strongly_connected_components_max_flow_lab ├── articulation_points │ ├── ArticulationPoints.java │ ├── EdmondsKarp.java │ ├── Main.java │ └── StronglyConnectedComponents.java ├── max_flow │ ├── ArticulationPoints.java │ ├── EdmondsKarp.java │ ├── Main.java │ └── StronglyConnectedComponents.java └── strongly_connected_components │ ├── ArticulationPoints.java │ ├── EdmondsKarp.java │ ├── Main.java │ └── StronglyConnectedComponents.java ├── introduction_to_dynamic_programming_lab ├── Fibonacci.java ├── LongestIncreasingSubsequence.java ├── MoveDownRight.java └── RodCutting.java ├── recursion_and_backtracking ├── EightQueensPuzzle.java ├── GeneratingZeroOneVectors.java ├── PathsInLabyrinth.java ├── RecursiveArraySum.java ├── RecursiveDrawing.java ├── RecursiveFactorial.java └── RecursiveFibonacci.java ├── recursion_and_combinatorial_exercise ├── Cinema.java ├── CombinationsWithRepetition.java ├── CombinationsWithoutRepetition.java ├── ConnectedAreasInMatrix.java ├── NestedLoops.java ├── ReverseArray.java ├── SchoolTeams.java ├── TowersOfHanoi.java └── WordCruncher.java └── searching_sorting_and_greedy_algorithms ├── BinarySearch.java ├── MergeSort.java ├── QuickSort.java ├── SetCover.java └── SumOfCoins.java /.gitignore: -------------------------------------------------------------------------------- 1 | #Output directory 2 | /out/ 3 | #Idea folder 4 | /.idea/ 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms With Java 2 | This repository contains the solutions for mutiple algorithms. Many of wich are well known solutions and some interesting usages of them in differetn problems. 3 | -------------------------------------------------------------------------------- /algorithms-with-java.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/advanced_exam_preparation/ChainLightning.java: -------------------------------------------------------------------------------- 1 | package advanced_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.*; 7 | 8 | public class ChainLightning { 9 | 10 | public static class Edge implements Comparable { 11 | int from; 12 | int to; 13 | int weight; 14 | 15 | public Edge(int from, int to, int weight) { 16 | this.from = from; 17 | this.to = to; 18 | this.weight = weight; 19 | } 20 | 21 | @Override 22 | public int compareTo(Edge other) { 23 | return Integer.compare(this.weight, other.weight); 24 | } 25 | } 26 | 27 | public static List[] graph; 28 | public static boolean[] visited; 29 | public static int[] damage; 30 | public static int max = Integer.MIN_VALUE; 31 | 32 | public static Map> forest = new HashMap<>(); 33 | 34 | @SuppressWarnings("unchecked") 35 | public static void main(String[] args) throws IOException { 36 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 37 | 38 | int nodes = Integer.parseInt(reader.readLine()); 39 | int edges = Integer.parseInt(reader.readLine()); 40 | int hitsCount = Integer.parseInt(reader.readLine()); 41 | 42 | visited = new boolean[nodes]; 43 | graph = new ArrayList[nodes]; 44 | damage = new int[nodes]; 45 | 46 | for (int i = 0; i < edges; i++) { 47 | int[] tokens = Arrays.stream(reader.readLine().split("\\s+")) 48 | .mapToInt(Integer::parseInt) 49 | .toArray(); 50 | 51 | int from = tokens[0]; 52 | int to = tokens[1]; 53 | int weight = tokens[2]; 54 | 55 | Edge edge = new Edge(from, to, weight); 56 | 57 | if (graph[from] == null) { 58 | graph[from] = new ArrayList<>(); 59 | } 60 | if (graph[to] == null) { 61 | graph[to] = new ArrayList<>(); 62 | } 63 | 64 | graph[from].add(edge); 65 | graph[to].add(edge); 66 | } 67 | 68 | for (int i = 0; i < nodes; i++) { 69 | if (!visited[i]) { 70 | msf(i); 71 | } 72 | } 73 | 74 | for (int i = 0; i < hitsCount; i++) { 75 | int[] tokens = Arrays.stream(reader.readLine().split("\\s+")) 76 | .mapToInt(Integer::parseInt) 77 | .toArray(); 78 | 79 | int parent = tokens[0]; 80 | int power = tokens[1]; 81 | 82 | damageNodes(parent, parent, power); 83 | } 84 | 85 | System.out.println(max); 86 | } 87 | 88 | private static void damageNodes(int parent, int next, int power) { 89 | 90 | if (power < 1) { 91 | return; 92 | } 93 | 94 | damage[parent] += power; 95 | if (max < damage[parent]) { 96 | max = damage[parent]; 97 | } 98 | if (forest.get(parent) != null) { 99 | for (int child : forest.get(parent)) { 100 | if (child != next) { 101 | damageNodes(child, parent, power / 2); 102 | } 103 | } 104 | } 105 | } 106 | 107 | private static void msf(int node) { 108 | PriorityQueue queue = new PriorityQueue<>(); 109 | visitNodes(node, queue); 110 | 111 | while (!queue.isEmpty()) { 112 | Edge minEdge = queue.poll(); 113 | 114 | int from = minEdge.from; 115 | int to = minEdge.to; 116 | 117 | if (visited[from] && visited[to]) { 118 | continue; 119 | } 120 | 121 | forest.putIfAbsent(from, new ArrayList<>()); 122 | forest.putIfAbsent(to, new ArrayList<>()); 123 | 124 | forest.get(from).add(to); 125 | forest.get(to).add(from); 126 | 127 | if (!visited[from]) { 128 | visitNodes(from, queue); 129 | } else { 130 | visitNodes(to, queue); 131 | } 132 | } 133 | } 134 | 135 | private static void visitNodes(int node, PriorityQueue queue) { 136 | 137 | visited[node] = true; 138 | if (graph[node] != null) { 139 | for (Edge edge : graph[node]) { 140 | int nextNode = node == edge.from ? edge.to : edge.from; 141 | if (!visited[nextNode]) { 142 | queue.offer(edge); 143 | } 144 | } 145 | } 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /src/advanced_exam_preparation/RoadTrip.java: -------------------------------------------------------------------------------- 1 | package advanced_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.Arrays; 7 | 8 | public class RoadTrip { 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 11 | 12 | int[] values = Arrays.stream(reader.readLine().split(", ")) 13 | .mapToInt(Integer::parseInt) 14 | .toArray(); 15 | 16 | int[] capacities = Arrays.stream(reader.readLine().split(", ")) 17 | .mapToInt(Integer::parseInt) 18 | .toArray(); 19 | 20 | int trunkCapacity = Integer.parseInt(reader.readLine()); 21 | 22 | int[][] dp = new int[values.length + 1][trunkCapacity + 1]; 23 | 24 | for (int i = 1; i <= values.length; i++) { 25 | for (int j = 1; j <= trunkCapacity; j++) { 26 | if (capacities[i - 1] <= j) { 27 | dp[i][j] = Math.max(values[i - 1] + dp[i - 1][j - capacities[i - 1]], 28 | dp[i - 1][j]); 29 | } else { 30 | dp[i][j] = dp[i - 1][j]; 31 | } 32 | } 33 | } 34 | 35 | System.out.println("Maximum value: " + dp[values.length][trunkCapacity]); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/advanced_exam_preparation/TourDeSofia.java: -------------------------------------------------------------------------------- 1 | package advanced_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.*; 7 | 8 | public class TourDeSofia { 9 | 10 | public static Map> graph = new HashMap<>(); 11 | public static boolean[] visited; 12 | public static int[] distances; 13 | 14 | public static void main(String[] args) throws IOException { 15 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 16 | 17 | int nodes = Integer.parseInt(reader.readLine()); 18 | int edges = Integer.parseInt(reader.readLine()); 19 | int source = Integer.parseInt(reader.readLine()); 20 | 21 | visited = new boolean[nodes]; 22 | distances = new int[nodes]; 23 | 24 | for (int i = 0; i < edges; i++) { 25 | int[] tokens = Arrays.stream(reader.readLine().split("\\s+")) 26 | .mapToInt(Integer::parseInt) 27 | .toArray(); 28 | 29 | graph.putIfAbsent(tokens[0], new ArrayList<>()); 30 | graph.get(tokens[0]).add(tokens[1]); 31 | } 32 | 33 | bfs(source); 34 | 35 | if (distances[source] != 0) { 36 | System.out.println(distances[source]); 37 | } else { 38 | int visitedNodes = 0; 39 | for (boolean node : visited) { 40 | if (node) { 41 | visitedNodes++; 42 | } 43 | } 44 | System.out.println(visitedNodes); 45 | } 46 | } 47 | 48 | private static void bfs(int source) { 49 | 50 | Deque queue = new ArrayDeque<>(); 51 | 52 | queue.offer(source); 53 | 54 | visited[source] = true; 55 | distances[source] = 0; 56 | 57 | while (!queue.isEmpty()) { 58 | int parent = queue.poll(); 59 | List children = graph.get(parent); 60 | if (children != null) { 61 | for (int child : children) { 62 | if (!visited[child]) { 63 | visited[child] = true; 64 | queue.offer(child); 65 | distances[child] = distances[parent] + 1; 66 | } else if (child == source && distances[child] == 0) { 67 | distances[child] = distances[parent] + 1; 68 | return; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/combinatorial_problems/CombinationsWithRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CombinationsWithRepetition { 6 | 7 | public static String[] elements; 8 | public static String[] variations; 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | elements = scanner.nextLine().split("\\s+"); 14 | 15 | int k = Integer.parseInt(scanner.nextLine()); 16 | 17 | variations = new String[k]; 18 | 19 | combinations(0, 0); 20 | } 21 | 22 | private static void combinations(int index, int start) { 23 | if (index == variations.length) { 24 | print(variations); 25 | return; 26 | } 27 | 28 | for (int i = start; i < elements.length; i++) { 29 | variations[index] = elements[i]; 30 | combinations(index + 1, i); 31 | } 32 | } 33 | 34 | private static void print(String[] arr) { 35 | System.out.println(String.join(" ", arr)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/combinatorial_problems/CombinationsWithoutRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CombinationsWithoutRepetition { 6 | 7 | public static String[] elements; 8 | public static String[] variations; 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | elements = scanner.nextLine().split("\\s+"); 14 | 15 | int k = Integer.parseInt(scanner.nextLine()); 16 | 17 | variations = new String[k]; 18 | 19 | combinations(0, 0); 20 | } 21 | 22 | private static void combinations(int index, int start) { 23 | if (index == variations.length) { 24 | print(variations); 25 | return; 26 | } 27 | 28 | for (int i = start; i < elements.length; i++) { 29 | variations[index] = elements[i]; 30 | combinations(index + 1, i + 1); 31 | } 32 | } 33 | 34 | private static void print(String[] arr) { 35 | System.out.println(String.join(" ", arr)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/combinatorial_problems/NChooseKCount.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class NChooseKCount { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int n = Integer.parseInt(scanner.nextLine()); 10 | 11 | int k = Integer.parseInt(scanner.nextLine()); 12 | 13 | int binomial = binomial(n, k); 14 | 15 | System.out.println(binomial); 16 | } 17 | 18 | private static int binomial(int n, int k) { 19 | if (k > n) { 20 | return 0; 21 | } 22 | if (k == 0 || k == n) { 23 | return 1; 24 | } 25 | 26 | return binomial(n - 1, k - 1) + binomial(n - 1, k); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/combinatorial_problems/PermutationsWithRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.HashSet; 4 | import java.util.Scanner; 5 | 6 | public class PermutationsWithRepetition { 7 | 8 | public static String[] elements; 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | elements = scanner.nextLine().split("\\s+"); 14 | 15 | permute(0); 16 | } 17 | 18 | private static void permute(int index) { 19 | if (index == elements.length) { 20 | print(elements); 21 | return; 22 | } 23 | 24 | permute(index + 1); 25 | HashSet swapped = new HashSet<>(); 26 | swapped.add(elements[index]); 27 | for (int i = index + 1; i < elements.length; i++) { 28 | if (!swapped.contains(elements[i])) { 29 | swap(elements, index, i); 30 | permute(index + 1); 31 | swap(elements, index, i); 32 | swapped.add(elements[i]); 33 | } 34 | } 35 | } 36 | 37 | private static void swap(String[] arr, int first, int second) { 38 | String temp = arr[first]; 39 | arr[first] = arr[second]; 40 | arr[second] = temp; 41 | } 42 | 43 | private static void print(String[] arr) { 44 | System.out.println(String.join(" ", arr)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/combinatorial_problems/PermutationsWithoutRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class PermutationsWithoutRepetition { 6 | 7 | public static String[] elements; 8 | public static String[] permutes; 9 | public static boolean[] used; 10 | 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | 14 | elements = scanner.nextLine().split("\\s+"); 15 | 16 | permutes = new String[elements.length]; 17 | used = new boolean[elements.length]; 18 | 19 | 20 | permute(0); 21 | } 22 | 23 | private static void permute(int index) { 24 | if (index == elements.length) { 25 | print(); 26 | return; 27 | } 28 | 29 | for (int i = 0; i < elements.length; i++) { 30 | if (!used[i]) { 31 | used[i] = true; 32 | permutes[index] = elements[i]; 33 | permute(index + 1); 34 | used[i] = false; 35 | } 36 | } 37 | } 38 | 39 | private static void print() { 40 | System.out.println(String.join(" ", permutes)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/combinatorial_problems/VariationsWithRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class VariationsWithRepetition { 6 | 7 | public static String[] elements; 8 | public static String[] variations; 9 | public static boolean[] used; 10 | 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | 14 | elements = scanner.nextLine().split("\\s+"); 15 | 16 | int k = Integer.parseInt(scanner.nextLine()); 17 | 18 | variations = new String[k]; 19 | 20 | used = new boolean[elements.length]; 21 | 22 | variations(0); 23 | } 24 | 25 | private static void variations(int index) { 26 | if (index == variations.length) { 27 | print(variations); 28 | return; 29 | } 30 | 31 | for (String element : elements) { 32 | variations[index] = element; 33 | variations(index + 1); 34 | } 35 | } 36 | 37 | private static void swap(String[] arr, int first, int second) { 38 | String temp = arr[first]; 39 | arr[first] = arr[second]; 40 | arr[second] = temp; 41 | } 42 | 43 | private static void print(String[] arr) { 44 | System.out.println(String.join(" ", arr)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/combinatorial_problems/VariationsWithoutRepetition.java: -------------------------------------------------------------------------------- 1 | package combinatorial_problems; 2 | 3 | import java.util.Scanner; 4 | 5 | public class VariationsWithoutRepetition { 6 | 7 | public static String[] elements; 8 | public static String[] variations; 9 | public static boolean[] used; 10 | 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | 14 | elements = scanner.nextLine().split("\\s+"); 15 | 16 | int k = Integer.parseInt(scanner.nextLine()); 17 | 18 | variations = new String[k]; 19 | 20 | used = new boolean[elements.length]; 21 | 22 | variations(0); 23 | } 24 | 25 | private static void variations(int index) { 26 | if (index == variations.length) { 27 | print(variations); 28 | return; 29 | } 30 | 31 | for (int i = 0; i < elements.length; i++) { 32 | if (!used[i]) { 33 | used[i] = true; 34 | variations[index] = elements[i]; 35 | variations(index + 1); 36 | used[i] = false; 37 | } 38 | } 39 | } 40 | 41 | private static void swap(String[] arr, int first, int second) { 42 | String temp = arr[first]; 43 | arr[first] = arr[second]; 44 | arr[second] = temp; 45 | } 46 | 47 | private static void print(String[] arr) { 48 | System.out.println(String.join(" ", arr)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_exercise/AbaspaBasapa.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_exercise; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Scanner; 7 | 8 | public class AbaspaBasapa { 9 | 10 | public static int[][] dp; 11 | 12 | public static void main(String[] args) { 13 | Scanner scanner = new Scanner(System.in); 14 | 15 | String first = scanner.nextLine(); 16 | String second = scanner.nextLine(); 17 | 18 | dp = new int[first.length()][second.length()]; 19 | 20 | int bestLength = -1; 21 | int bestRow = -1; 22 | int bestCol = -1; 23 | 24 | for (int rowIndex = 0; rowIndex < first.length(); rowIndex++) { 25 | for (int colIndex = 0; colIndex < second.length(); colIndex++) { 26 | if (first.charAt(rowIndex) == second.charAt(colIndex)) { 27 | dp[rowIndex][colIndex] = getPrevBest(rowIndex, colIndex) + 1; 28 | } 29 | 30 | if (dp[rowIndex][colIndex] > bestLength) { 31 | bestLength = dp[rowIndex][colIndex]; 32 | bestRow = rowIndex; 33 | bestCol = colIndex; 34 | } 35 | } 36 | } 37 | 38 | List result = new ArrayList<>(); 39 | 40 | while (bestRow >= 0 && bestCol >= 0 && dp[bestRow][bestCol] != 0) { 41 | result.add(first.charAt(bestRow)); 42 | bestRow--; 43 | bestCol--; 44 | 45 | if (bestRow == -1 && bestCol >= 0) { 46 | bestRow = 0; 47 | } 48 | if (bestCol == -1 && bestRow >= 0) { 49 | bestCol = 0; 50 | } 51 | } 52 | 53 | Collections.reverse(result); 54 | 55 | for (Character character : result) { 56 | System.out.print(character); 57 | } 58 | } 59 | 60 | private static int getPrevBest(int rowIndex, int colIndex) { 61 | if (rowIndex - 1 < 0 || colIndex - 1 < 0) { 62 | return 0; 63 | } 64 | 65 | return dp[rowIndex - 1][colIndex - 1]; 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_exercise/RectangleIntersection.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_exercise; 2 | 3 | 4 | import java.util.*; 5 | 6 | /** 7 | * Calculates total area of all overlapping rectangles without the overlapping. 8 | * We divide the rectangles into horizontal sections in which there is no change in the vertical 9 | * section. This means that we have a delta X for which the Y should be a constant. The solution is to 10 | * sum all the delta X for its specific Y. 11 | *

12 | * There is a more optimal solution using interval trees to optimize the storing of overlapping 13 | * rectangle sections. 14 | */ 15 | public class RectangleIntersection { 16 | public static class Point { 17 | private int coordinate; 18 | private boolean isEnd; 19 | 20 | public Point(int coordinate, boolean isEnd) { 21 | this.coordinate = coordinate; 22 | this.isEnd = isEnd; 23 | } 24 | 25 | public int getCoordinate() { 26 | return coordinate; 27 | } 28 | 29 | public boolean isEnd() { 30 | return isEnd; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "Point{" + 36 | "coordinate=" + coordinate + 37 | ", isEnd=" + isEnd + 38 | '}'; 39 | } 40 | } 41 | 42 | private static class Rectangle { 43 | private Point minX; 44 | private Point maxX; 45 | private Point minY; 46 | private Point maxY; 47 | 48 | public Rectangle(Point minX, Point maxX, Point minY, Point maxY) { 49 | this.minX = minX; 50 | this.maxX = maxX; 51 | this.minY = minY; 52 | this.maxY = maxY; 53 | } 54 | 55 | public Point getMinX() { 56 | return minX; 57 | } 58 | 59 | public Point getMaxX() { 60 | return maxX; 61 | } 62 | 63 | public Point getMinY() { 64 | return minY; 65 | } 66 | 67 | public Point getMaxY() { 68 | return maxY; 69 | } 70 | 71 | public int getArea() { 72 | return (maxX.getCoordinate() - minX.getCoordinate()) * (maxY.getCoordinate() - minY.getCoordinate()); 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "Rectangle{" + 78 | "minX=" + minX + 79 | ", maxX=" + maxX + 80 | ", minY=" + minY + 81 | ", maxY=" + maxY + 82 | '}'; 83 | } 84 | } 85 | 86 | public static class Section { 87 | private int start; 88 | private int end; 89 | private List heightPoints; 90 | 91 | public Section(int start, int end) { 92 | this.start = start; 93 | this.end = end; 94 | this.heightPoints = new ArrayList<>(); 95 | } 96 | 97 | public int getStart() { 98 | return start; 99 | } 100 | 101 | public int getEnd() { 102 | return end; 103 | } 104 | 105 | public List getHeightPoints() { 106 | return heightPoints; 107 | } 108 | 109 | @Override 110 | public String toString() { 111 | return "Section{" + 112 | "start=" + start + 113 | ", end=" + end + 114 | ", heightPoints=" + heightPoints + 115 | '}'; 116 | } 117 | } 118 | 119 | public static void main(String[] args) { 120 | Scanner scanner = new Scanner(System.in); 121 | int rectangleCount = Integer.parseInt(scanner.nextLine()); 122 | 123 | List rectangles = new ArrayList<>(); 124 | List horizontalCoordinatePoints = new ArrayList<>(); 125 | 126 | for (int i = 0; i < rectangleCount; i++) { 127 | int[] coordinates = Arrays.stream(scanner.nextLine().split("\\s+")) 128 | .mapToInt(Integer::parseInt) 129 | .toArray(); 130 | Point minX = new Point(coordinates[0], false); 131 | Point maxX = new Point(coordinates[1], true); 132 | Point minY = new Point(coordinates[2], false); 133 | Point maxY = new Point(coordinates[3], true); 134 | 135 | rectangles.add(new Rectangle(minX, maxX, minY, maxY)); 136 | horizontalCoordinatePoints.add(minX); 137 | horizontalCoordinatePoints.add(maxX); 138 | } 139 | 140 | rectangles.sort(Comparator.comparingInt(f -> f.getMinX().getCoordinate())); 141 | horizontalCoordinatePoints.sort(Comparator.comparing(Point::getCoordinate)); 142 | 143 | List

sections = new LinkedList<>(); 144 | 145 | for (int i = 1; i < horizontalCoordinatePoints.size(); i++) { 146 | Point start = horizontalCoordinatePoints.get(i - 1); 147 | Point end = horizontalCoordinatePoints.get(i); 148 | 149 | Section section = new Section(start.getCoordinate(), end.getCoordinate()); 150 | 151 | sections.add(section); 152 | } 153 | 154 | for (Rectangle rectangle : rectangles) { 155 | int start = rectangle.getMinX().getCoordinate(); 156 | int end = rectangle.getMaxX().getCoordinate(); 157 | for (Section section : sections) { 158 | if (section.getStart() == start 159 | || section.getEnd() == end 160 | || (section.getEnd() < end && section.getStart() > start)) { 161 | section.getHeightPoints().add(rectangle.getMinY()); 162 | section.getHeightPoints().add(rectangle.getMaxY()); 163 | } 164 | } 165 | } 166 | 167 | int area = 0; 168 | for (Section section : sections) { 169 | if (section.getHeightPoints().size() < 4) { 170 | continue; 171 | } 172 | 173 | int width = section.getEnd() - section.getStart(); 174 | int height = calculateLineCoverLength(section.getHeightPoints(), 2); 175 | 176 | area += width * height; 177 | } 178 | 179 | System.out.println(area); 180 | } 181 | 182 | /** 183 | * Used to find the overlapping of Y of each rectangle 184 | * 185 | * @param points - each staring and ending point of each rectangle 186 | * @param coverRequired - the amount of times that the lines must overlap 187 | * @return - the length of the needed overlap 188 | */ 189 | public static int calculateLineCoverLength(List points, int coverRequired) { 190 | points.sort(Comparator.comparing(Point::getCoordinate)); 191 | 192 | int lineCoverCount = 0; 193 | int start = points.get(0).getCoordinate(); 194 | int coverLength = 0; 195 | 196 | for (Point point : points) { 197 | if (lineCoverCount >= coverRequired) { 198 | coverLength = coverLength + (point.getCoordinate() - start); 199 | } 200 | 201 | if (!point.isEnd()) { 202 | lineCoverCount++; 203 | } else { 204 | lineCoverCount--; 205 | } 206 | 207 | start = point.getCoordinate(); 208 | } 209 | 210 | return coverLength; 211 | } 212 | 213 | } 214 | 215 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_exercise/TheMadGardener.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_exercise; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class TheMadGardener { 7 | 8 | public static class Sequence { 9 | int size; 10 | int prev; 11 | int sum; 12 | } 13 | 14 | public static void main(String[] args) { 15 | Scanner scanner = new Scanner(System.in); 16 | 17 | int[] input = Arrays.stream(scanner.nextLine().split("\\s+")) 18 | .mapToInt(Integer::parseInt) 19 | .toArray(); 20 | 21 | int[] plants = new int[input.length + 1]; 22 | 23 | for (int i = 1; i < plants.length; i++) { 24 | plants[i] = input[i - 1]; 25 | } 26 | 27 | Sequence[] firstLIS = getLIS(plants); 28 | 29 | int[] reversed = new int[plants.length]; 30 | 31 | for (int i = 1; i < input.length; i++) { 32 | reversed[i] = plants[(plants.length - 1) - i + 1]; 33 | } 34 | 35 | Sequence[] secondLIS = getLIS(reversed); 36 | 37 | int maxSize = 0; 38 | int maxSum = 0; 39 | int peek = 0; 40 | 41 | int end = plants.length - 1; 42 | 43 | for (int i = 1; i < plants.length; i++) { 44 | int size = firstLIS[i].size + secondLIS[end - i + 1].size; 45 | if (size >= maxSize) { 46 | maxSize = size; 47 | maxSum = firstLIS[i].sum + secondLIS[end - i + 1].sum - plants[i]; 48 | peek = i; 49 | } 50 | } 51 | 52 | int[] result = new int[plants.length]; 53 | 54 | int element = firstLIS[peek].size; 55 | 56 | int index = peek; 57 | 58 | int nextElement = 0; 59 | 60 | while (index != 0) { 61 | nextElement++; 62 | result[element--] = plants[index]; 63 | index = firstLIS[index].prev; 64 | } 65 | 66 | index = secondLIS[plants.length - peek].prev; 67 | 68 | while (index != 0) { 69 | result[++nextElement] = reversed[index]; 70 | index = secondLIS[index].prev; 71 | } 72 | 73 | 74 | for (int i = 1; i < maxSize; i++) { 75 | System.out.print(result[i] + " "); 76 | } 77 | 78 | System.out.println(); 79 | 80 | System.out.printf("%.2f%n", maxSum / ((maxSize - 1) * 1.00)); 81 | 82 | System.out.println(maxSize - 1); 83 | 84 | } 85 | 86 | private static Sequence[] getLIS(int[] plants) { 87 | Sequence[] LIS = new Sequence[plants.length]; 88 | 89 | LIS[0] = new Sequence(); 90 | 91 | for (int i = 1; i <= plants.length - 1; i++) { 92 | LIS[i] = new Sequence(); 93 | for (int j = 0; j < i; j++) { 94 | if (plants[j] <= plants[i]) { 95 | if (LIS[j].size + 1 > LIS[i].size 96 | || ((LIS[j].size + 1 == LIS[i].size) && LIS[j].sum + plants[i] > LIS[i].sum)) { 97 | LIS[i].sum = LIS[j].sum + plants[i]; 98 | LIS[i].size = LIS[i].size + 1; 99 | LIS[i].prev = j; 100 | } 101 | } 102 | } 103 | } 104 | 105 | return LIS; 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_exercise/ZigzagMatrix.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_exercise; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class ZigzagMatrix { 7 | 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | int rows = Integer.parseInt(scanner.nextLine()); 12 | int cols = Integer.parseInt(scanner.nextLine()); 13 | 14 | int[][] matrix = new int[rows][cols]; 15 | 16 | for (int row = 0; row < rows; row++) { 17 | matrix[row] = Arrays.stream(scanner.nextLine().split(",")) 18 | .mapToInt(Integer::parseInt) 19 | .toArray(); 20 | } 21 | 22 | int[][] maxDp = new int[rows][cols]; 23 | int[][] prevs = new int[rows][cols]; 24 | 25 | for (int row = 1; row < rows; row++) { 26 | maxDp[row][0] = matrix[row][0]; 27 | } 28 | 29 | for (int col = 1; col < cols; col++) { 30 | for (int row = 0; row < rows; row++) { 31 | int prevMax = 0; 32 | 33 | if (col % 2 != 0) { 34 | for (int i = row + 1; i < rows; i++) { 35 | if (maxDp[i][col - 1] > prevMax) { 36 | prevMax = maxDp[i][col - 1]; 37 | prevs[row][col] = i; 38 | } 39 | } 40 | } else { 41 | for (int i = 0; i < row; i++) { 42 | if (maxDp[i][col - 1] > prevMax) { 43 | prevMax = maxDp[i][col - 1]; 44 | prevs[row][col] = i; 45 | } 46 | } 47 | } 48 | maxDp[row][col] = prevMax + matrix[row][col]; 49 | } 50 | } 51 | 52 | List result = new ArrayList<>(); 53 | 54 | int index = cols - 1; 55 | int rowIndex = 0; 56 | 57 | int max = -1; 58 | 59 | for (int row = 0; row < maxDp.length; row++) { 60 | if (maxDp[row][index] > max) { 61 | rowIndex = row; 62 | max = maxDp[row][index]; 63 | } 64 | } 65 | 66 | while (index >= 0) { 67 | result.add(matrix[rowIndex][index]); 68 | rowIndex = prevs[rowIndex][index]; 69 | index--; 70 | } 71 | 72 | Collections.reverse(result); 73 | 74 | System.out.println(result.stream().mapToInt(e -> e).sum() + " = " + result.stream().map(String::valueOf) 75 | .collect(Collectors.joining(" + "))); 76 | 77 | 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_lab/Knapsack.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_lab; 2 | 3 | import java.util.*; 4 | 5 | public class Knapsack { 6 | public static class Item implements Comparable { 7 | String name; 8 | int weight; 9 | int price; 10 | 11 | Item(String name, int weight, int price) { 12 | this.name = name; 13 | this.weight = weight; 14 | this.price = price; 15 | } 16 | 17 | @Override 18 | public int compareTo(Item other) { 19 | return this.name.compareTo(other.name); 20 | } 21 | } 22 | 23 | public static void main(String[] args) { 24 | Scanner scanner = new Scanner(System.in); 25 | 26 | int capacity = Integer.parseInt(scanner.nextLine()); 27 | 28 | String line = scanner.nextLine(); 29 | 30 | List items = new ArrayList<>(); 31 | 32 | while (!line.equals("end")) { 33 | 34 | String[] tokens = line.split("\\s+"); 35 | 36 | items.add(new Item(tokens[0], Integer.parseInt(tokens[1]), Integer.parseInt(tokens[2]))); 37 | 38 | line = scanner.nextLine(); 39 | } 40 | 41 | int[][] dp = new int[items.size() + 1][capacity + 1]; 42 | boolean[][] takenItems = new boolean[items.size() + 1][capacity + 1]; 43 | 44 | for (int itemRow = 1; itemRow <= items.size(); itemRow++) { 45 | Item item = items.get(itemRow - 1); 46 | 47 | for (int capacityCol = 0; capacityCol <= capacity; capacityCol++) { 48 | 49 | int excluded = dp[itemRow - 1][capacityCol]; 50 | if (capacityCol - item.weight < 0) { 51 | dp[itemRow][capacityCol] = excluded; 52 | } else { 53 | int included = dp[itemRow - 1][capacityCol - item.weight] + item.price; 54 | 55 | if (excluded > included) { 56 | dp[itemRow][capacityCol] = excluded; 57 | } else { 58 | dp[itemRow][capacityCol] = included; 59 | takenItems[itemRow][capacityCol] = true; 60 | } 61 | } 62 | } 63 | } 64 | 65 | int weight = capacity; 66 | 67 | int bestValue = dp[items.size()][capacity]; 68 | 69 | while (dp[items.size()][weight - 1] == bestValue) { 70 | weight--; 71 | } 72 | 73 | Set result = new TreeSet<>(); 74 | 75 | int lastItem = items.size(); 76 | 77 | while (lastItem > 0) { 78 | if (takenItems[lastItem][capacity]) { 79 | Item item = items.get(lastItem - 1); 80 | result.add(item); 81 | capacity -= item.weight; 82 | } 83 | lastItem--; 84 | } 85 | 86 | System.out.println("Total Weight: " + weight); 87 | System.out.println("Total Value: " + bestValue); 88 | 89 | for (Item item : result) { 90 | System.out.println(item.name); 91 | } 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/dynamic_programming_advanced_lab/LCS.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_advanced_lab; 2 | 3 | import java.util.Scanner; 4 | 5 | public class LCS { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | String first = scanner.nextLine(); 10 | String second = scanner.nextLine(); 11 | 12 | int[][] dp = new int[first.length() + 1][second.length() + 1]; 13 | 14 | for (int rowIndex = 1; rowIndex <= first.length(); rowIndex++) { 15 | for (int colIndex = 1; colIndex <= second.length(); colIndex++) { 16 | if (first.charAt(rowIndex - 1) == second.charAt(colIndex - 1)) { 17 | dp[rowIndex][colIndex] = 18 | dp[rowIndex - 1][colIndex - 1] + 1; 19 | } else { 20 | dp[rowIndex][colIndex] = Math.max( 21 | dp[rowIndex - 1][colIndex], dp[rowIndex][colIndex - 1] 22 | ); 23 | } 24 | } 25 | } 26 | 27 | System.out.println(dp[first.length()][second.length()]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/BinomialCoefficients.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.Scanner; 4 | 5 | public class BinomialCoefficients { 6 | public static long memory[][]; 7 | 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | int n = Integer.parseInt(scanner.nextLine()); 12 | int k = Integer.parseInt(scanner.nextLine()); 13 | 14 | memory = new long[n + 1][k + 1]; 15 | 16 | long binom = calcBinom(n, k); 17 | 18 | System.out.println(binom); 19 | } 20 | 21 | private static long calcBinom(int n, int k) { 22 | if (k == 0 || k == n) { 23 | return 1; 24 | } 25 | 26 | if (memory[n][k] != 0) { 27 | return memory[n][k]; 28 | } 29 | 30 | return memory[n][k] = calcBinom(n - 1, k) + calcBinom(n - 1, k - 1); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/ConnectingCables.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class ConnectingCables { 7 | public static void main(String[] args) { 8 | Scanner scanner = new Scanner(System.in); 9 | 10 | int[] cables = Arrays.stream(scanner.nextLine().split("\\s+")) 11 | .mapToInt(Integer::parseInt) 12 | .toArray(); 13 | 14 | int[] destinations = new int[cables.length]; 15 | 16 | for (int i = 0; i < destinations.length; i++) { 17 | destinations[i] = i + 1; 18 | } 19 | 20 | int[][] dp = new int[cables.length + 1][cables.length + 1]; 21 | 22 | for (int i = 1; i <= cables.length; i++) { 23 | for (int j = 1; j <= cables.length; j++) { 24 | if (destinations[i - 1] == cables[j - 1]) { 25 | dp[i][j] = dp[i - 1][j - 1] + 1; 26 | } else { 27 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 28 | } 29 | } 30 | } 31 | 32 | System.out.println("Maximum pairs connected: " + dp[cables.length][cables.length]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/DividingPresents.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.Arrays; 7 | import java.util.stream.IntStream; 8 | 9 | public class DividingPresents { 10 | public static void main(String[] args) throws IOException { 11 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 12 | 13 | int[] presents = Arrays.stream(reader.readLine().split("\\s+")) 14 | .mapToInt(Integer::parseInt) 15 | .toArray(); 16 | 17 | int totalSum = IntStream.of(presents).sum(); 18 | 19 | int[] sums = new int[totalSum + 1]; 20 | 21 | for (int i = 1; i < sums.length; i++) { 22 | sums[i] = -1; 23 | } 24 | 25 | for (int i = 0; i < presents.length; i++) { 26 | for (int prevSumIndex = totalSum - presents[i]; prevSumIndex >= 0; prevSumIndex--) { 27 | int presentValue = presents[i]; 28 | 29 | if (sums[prevSumIndex] != -1 && sums[prevSumIndex + presentValue] == -1) { 30 | sums[prevSumIndex + presentValue] = i; 31 | } 32 | } 33 | } 34 | 35 | int half = totalSum / 2; 36 | 37 | for (int i = half; i >= 0; i--) { 38 | if (sums[i] == -1) { 39 | continue; 40 | } 41 | 42 | System.out.printf("Difference: %d%n", totalSum - i - i); 43 | System.out.printf("Alan:%d Bob:%d%n", i, totalSum - i); 44 | System.out.print("Alan takes:"); 45 | 46 | while (i != 0) { 47 | System.out.printf(" %d", presents[sums[i]]); 48 | i -= presents[sums[i]]; 49 | } 50 | 51 | System.out.println(); 52 | System.out.println("Bob takes the rest."); 53 | } 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/LongestZigZag.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Deque; 6 | import java.util.Scanner; 7 | 8 | public class LongestZigZag { 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | 12 | int[] numbers = Arrays.stream(scanner.nextLine().split("\\s+")) 13 | .mapToInt(Integer::parseInt) 14 | .toArray(); 15 | 16 | int[][] dp = new int[numbers.length + 1][2]; 17 | int[][] prev = new int[numbers.length + 1][2]; 18 | 19 | // Are Greater 20 | dp[0][0] = 1; 21 | // Are lesser 22 | dp[0][1] = 1; 23 | 24 | prev[0][0] = -1; 25 | prev[0][1] = -1; 26 | 27 | int maxLength = 0; 28 | 29 | int[] best = new int[2]; 30 | 31 | for (int currentIndex = 0; currentIndex < numbers.length; currentIndex++) { 32 | int currentNumber = numbers[currentIndex]; 33 | for (int prevIndex = currentIndex - 1; prevIndex >= 0; prevIndex--) { 34 | int prevNumber = numbers[prevIndex]; 35 | if (currentNumber > prevNumber && dp[currentIndex][0] <= dp[prevIndex][1] + 1) { 36 | dp[currentIndex][0] = dp[prevIndex][1] + 1; 37 | prev[currentIndex][0] = prevIndex; 38 | } 39 | if (currentNumber < prevNumber && dp[currentIndex][1] <= dp[prevIndex][0] + 1) { 40 | dp[currentIndex][1] = dp[prevIndex][0] + 1; 41 | prev[currentIndex][1] = prevIndex; 42 | } 43 | } 44 | 45 | 46 | if (maxLength < dp[currentIndex][0]) { 47 | maxLength = dp[currentIndex][0]; 48 | best[0] = currentIndex; 49 | best[1] = 0; 50 | } else if (maxLength < dp[currentIndex][1]) { 51 | maxLength = dp[currentIndex][1]; 52 | best[0] = currentIndex; 53 | best[1] = 1; 54 | } 55 | } 56 | 57 | Deque zigZagSequence = new ArrayDeque<>(); 58 | 59 | int beginRow = best[0]; 60 | while (beginRow >= 0) { 61 | zigZagSequence.push(numbers[beginRow]); 62 | beginRow = prev[beginRow][best[1]]; 63 | best[1] = best[1] == 0 ? 1 : 0; 64 | } 65 | 66 | while (!zigZagSequence.isEmpty()) { 67 | System.out.print(zigZagSequence.pop() + " "); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/MinimumEditDistance.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.Scanner; 4 | 5 | public class MinimumEditDistance { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int costReplace = Integer.parseInt(scanner.nextLine()); 10 | int costInsert = Integer.parseInt(scanner.nextLine()); 11 | int costDelete = Integer.parseInt(scanner.nextLine()); 12 | 13 | char[] first = scanner.nextLine().toCharArray(); 14 | char[] second = scanner.nextLine().toCharArray(); 15 | 16 | int[][] dp = new int[first.length + 1][second.length + 1]; 17 | 18 | for (int i = 1; i <= second.length; i++) { 19 | dp[0][i] = dp[0][i - 1] + costInsert; 20 | } 21 | 22 | for (int i = 1; i <= first.length; i++) { 23 | dp[i][0] = dp[i - 1][0] + costDelete; 24 | } 25 | 26 | for (int i = 1; i <= first.length; i++) { 27 | for (int j = 1; j <= second.length; j++) { 28 | if (first[i - 1] == second[j - 1]) { 29 | dp[i][j] = dp[i - 1][j - 1]; 30 | } else { 31 | int insert = dp[i][j - 1] + costInsert; 32 | int replace = dp[i - 1][j - 1] + costReplace; 33 | int delete = dp[i - 1][j] + costDelete; 34 | dp[i][j] = Math.min(insert, Math.min(replace, delete)); 35 | } 36 | } 37 | } 38 | 39 | System.out.println("Minimum edit distance: " + dp[first.length][second.length]); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/SumWithLimitedCoins.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class SumWithLimitedCoins { 12 | public static void main(String[] args) throws IOException { 13 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 14 | 15 | int[] array = Arrays.stream(br.readLine().split("\\s+")).mapToInt(Integer::parseInt).toArray(); 16 | 17 | int target = Integer.parseInt(br.readLine()); 18 | 19 | System.out.println(calcSum(array, target)); 20 | 21 | } 22 | 23 | private static int calcSum(int[] coins, int target) { 24 | Map result = new HashMap<>(); 25 | 26 | int answer = 0; 27 | 28 | result.put(0, 0); 29 | 30 | for (int currentCoin : coins) { 31 | for (Integer number : new ArrayList<>(result.keySet())) { 32 | int newSum = currentCoin + number; 33 | 34 | if (newSum == target) { 35 | answer++; 36 | } 37 | 38 | if (!result.containsKey(newSum)) { 39 | result.put(newSum, number); 40 | } 41 | } 42 | } 43 | 44 | return answer; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/SumWithUnlimitedCoins.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class SumWithUnlimitedCoins { 7 | public static void main(String[] args) { 8 | Scanner scanner = new Scanner(System.in); 9 | 10 | int[] coins = Arrays.stream(scanner.nextLine().split("\\s+")) 11 | .mapToInt(Integer::parseInt) 12 | .toArray(); 13 | 14 | int targetSum = Integer.parseInt(scanner.nextLine()); 15 | 16 | int[] dp = new int[targetSum + 1]; 17 | 18 | dp[0] = 1; 19 | 20 | for (int coin : coins) { 21 | for (int j = coin; j <= targetSum; j++) { 22 | dp[j] += dp[j - coin]; 23 | } 24 | } 25 | 26 | System.out.println(dp[targetSum]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/dynamic_programming_exercise/WordDifferences.java: -------------------------------------------------------------------------------- 1 | package dynamic_programming_exercise; 2 | 3 | import java.util.Scanner; 4 | 5 | public class WordDifferences { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | char[] first = scanner.nextLine().toCharArray(); 10 | char[] second = scanner.nextLine().toCharArray(); 11 | 12 | int[][] dp = new int[first.length + 1][second.length + 1]; 13 | 14 | for (int i = 0; i <= first.length; i++) { 15 | for (int j = 0; j <= second.length; j++) { 16 | if (i == 0) { 17 | dp[i][j] = j; 18 | } else if (j == 0) { 19 | dp[i][j] = i; 20 | } else if (first[i - 1] == second[j - 1]) { 21 | dp[i][j] = dp[i - 1][j - 1]; 22 | } else { 23 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1; 24 | } 25 | } 26 | } 27 | 28 | System.out.println("Deletions and Insertions: " + dp[first.length][second.length]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/fundamentals_exam_preparation/ClusterBorder.java: -------------------------------------------------------------------------------- 1 | package fundamentals_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | public class ClusterBorder { 11 | public static void main(String[] args) throws IOException { 12 | 13 | var reader = new BufferedReader(new InputStreamReader(System.in)); 14 | 15 | int[] singleShipTime = Arrays.stream(reader.readLine().split("\\s+")) 16 | .mapToInt(Integer::parseInt) 17 | .toArray(); 18 | 19 | int[] pairShipTime = Arrays.stream(reader.readLine().split("\\s+")) 20 | .mapToInt(Integer::parseInt) 21 | .toArray(); 22 | 23 | int[] dp = new int[singleShipTime.length + 1]; 24 | 25 | dp[1] = singleShipTime[0]; 26 | 27 | for (int i = 2; i <= singleShipTime.length; i++) { 28 | dp[i] = Math.min(dp[i - 1] + singleShipTime[i - 1], dp[i - 2] + pairShipTime[i - 2]); 29 | } 30 | 31 | System.out.println("Optimal Time: " + dp[singleShipTime.length]); 32 | 33 | List out = new ArrayList<>(); 34 | 35 | for (int i = dp.length - 1; i > 0; i--) { 36 | int timeDiffForLatestTwo = dp[i] - dp[i - 1]; 37 | if (timeDiffForLatestTwo == singleShipTime[i - 1]) { 38 | out.add("Single " + i); 39 | } else { 40 | out.add("Pair of " + (i - 1) + " and " + i); 41 | i--; 42 | } 43 | } 44 | 45 | for (int i = out.size() - 1; i >= 0; i--) { 46 | System.out.println(out.get(i)); 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/fundamentals_exam_preparation/Molecules.java: -------------------------------------------------------------------------------- 1 | package fundamentals_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayDeque; 7 | import java.util.Arrays; 8 | import java.util.Deque; 9 | 10 | public class Molecules { 11 | public static void main(String[] args) throws IOException { 12 | var reader = new BufferedReader(new InputStreamReader(System.in)); 13 | 14 | int nodes = Integer.parseInt(reader.readLine()); 15 | int edges = Integer.parseInt(reader.readLine()); 16 | 17 | int[][] graph = new int[nodes + 1][nodes + 1]; 18 | 19 | for (int i = 0; i < edges; i++) { 20 | int[] connections = Arrays.stream(reader.readLine().split("\\s+")) 21 | .mapToInt(Integer::parseInt) 22 | .toArray(); 23 | 24 | graph[connections[0]][connections[1]] = 1; 25 | } 26 | 27 | int start = Integer.parseInt(reader.readLine()); 28 | 29 | Deque queue = new ArrayDeque<>(); 30 | 31 | queue.offer(start); 32 | 33 | boolean[] visited = new boolean[nodes + 1]; 34 | 35 | while (!queue.isEmpty()) { 36 | int node = queue.poll(); 37 | visited[node] = true; 38 | for (int i = 0; i < graph[node].length; i++) { 39 | if (graph[node][i] != 0 && !visited[i]) { 40 | queue.offer(i); 41 | 42 | } 43 | } 44 | } 45 | 46 | for (int i = 1; i < visited.length; i++) { 47 | if (!visited[i]) { 48 | System.out.print(i + " "); 49 | } 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/fundamentals_exam_preparation/MonkeyBusiness.java: -------------------------------------------------------------------------------- 1 | package fundamentals_exam_preparation; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.Arrays; 7 | 8 | public class MonkeyBusiness { 9 | 10 | public static int n; 11 | public static int solutions = 0; 12 | public static int[] expression; 13 | public static StringBuilder out = new StringBuilder(); 14 | public static int[] numbers; 15 | 16 | public static void main(String[] args) throws IOException { 17 | var reader = new BufferedReader(new InputStreamReader(System.in)); 18 | 19 | n = Integer.parseInt(reader.readLine()); 20 | 21 | expression = new int[n]; 22 | numbers = new int[n]; 23 | 24 | for (int i = 0; i < n; i++) { 25 | numbers[i] = i + 1; 26 | } 27 | 28 | combinationsWithoutRep(0); 29 | 30 | out.append("Total Solutions: ").append(solutions); 31 | System.out.println(out.toString()); 32 | } 33 | 34 | private static void combinationsWithoutRep(int index) { 35 | if (index >= n) { 36 | printSolution(); 37 | } else { 38 | expression[index] = numbers[index]; 39 | combinationsWithoutRep(index + 1); 40 | expression[index] = -numbers[index]; 41 | combinationsWithoutRep(index + 1); 42 | } 43 | } 44 | 45 | private static void printSolution() { 46 | int sum = Arrays.stream(expression).sum(); 47 | if (sum == 0) { 48 | solutions++; 49 | for (int value : expression) { 50 | String numberAsStr = value > 0 ? "+" + value : String.valueOf(value); 51 | out.append(numberAsStr).append(" "); 52 | } 53 | out.append(System.lineSeparator()); 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths/ConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | 7 | public class ConnectedComponents { 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | int n = Integer.parseInt(scanner.nextLine()); 12 | 13 | List> graph = new ArrayList<>(); 14 | 15 | for (int i = 0; i < n; i++) { 16 | String nextLine = scanner.nextLine(); 17 | if (nextLine.trim().equals("")) { 18 | graph.add(new ArrayList<>()); 19 | } else { 20 | List nextNodes = Arrays.stream(nextLine.split("\\s+")) 21 | .map(Integer::parseInt) 22 | .collect(Collectors.toList()); 23 | graph.add(nextNodes); 24 | } 25 | 26 | } 27 | 28 | List> connectedComponents = getConnectedComponents(graph); 29 | 30 | for (Deque connectedComponent : connectedComponents) { 31 | System.out.print("Connected component: "); 32 | for (int integer : connectedComponent) { 33 | System.out.print(integer + " "); 34 | } 35 | System.out.println(); 36 | } 37 | } 38 | 39 | public static List> getConnectedComponents(List> graph) { 40 | boolean[] visited = new boolean[graph.size()]; 41 | List> components = new ArrayList<>(); 42 | 43 | for (int start = 0; start < graph.size(); start++) { 44 | if (!visited[start]) { 45 | components.add(new ArrayDeque<>()); 46 | bfs(start, components, graph, visited); 47 | } 48 | } 49 | 50 | return components; 51 | } 52 | 53 | private static void bfs(int start, List> components, List> graph, boolean[] visited) { 54 | Deque queue = new ArrayDeque<>(); 55 | visited[start] = true; 56 | queue.offer(start); 57 | 58 | while (!queue.isEmpty()) { 59 | int node = queue.poll(); 60 | 61 | components.get(components.size() - 1).offer(node); 62 | 63 | for (int child : graph.get(node)) { 64 | if (!visited[child]) { 65 | visited[child] = true; 66 | queue.offer(child); 67 | } 68 | } 69 | } 70 | } 71 | 72 | private static void dfs(int node, List> components, List> graph, boolean[] visited) { 73 | if (!visited[node]) { 74 | visited[node] = true; 75 | for (int child : graph.get(node)) { 76 | dfs(child, components, graph, visited); 77 | } 78 | components.get(components.size() - 1).offer(node); 79 | } 80 | } 81 | 82 | public static List topSort(Map> graph) { 83 | throw new AssertionError("Not Implemented"); 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths/ShortestPath.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths; 2 | 3 | import java.util.*; 4 | 5 | // This file also contains some additional methods 6 | public class ShortestPath { 7 | 8 | public static boolean[] visited; 9 | public static int[] prevNodes; 10 | 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | 14 | int n = Integer.parseInt(scanner.nextLine()); 15 | 16 | List> graph = new ArrayList<>(); 17 | 18 | for (int i = 0; i < n + 1; i++) { 19 | graph.add(new ArrayList<>()); 20 | } 21 | 22 | int edges = Integer.parseInt(scanner.nextLine()); 23 | 24 | for (int i = 0; i < edges; i++) { 25 | int[] paths = Arrays.stream(scanner.nextLine().split("\\s+")) 26 | .mapToInt(Integer::parseInt) 27 | .toArray(); 28 | 29 | graph.get(paths[0]).add(paths[1]); 30 | } 31 | 32 | int source = Integer.parseInt(scanner.nextLine()); 33 | int destination = Integer.parseInt(scanner.nextLine()); 34 | 35 | visited = new boolean[n + 1]; 36 | prevNodes = new int[n + 1]; 37 | 38 | Arrays.fill(prevNodes, -1); 39 | 40 | bfs(graph, source, destination); 41 | 42 | List path = new ArrayList<>(); 43 | 44 | path.add(destination); 45 | 46 | int prevNode = prevNodes[destination]; 47 | 48 | while (prevNode != -1) { 49 | path.add(prevNode); 50 | prevNode = prevNodes[prevNode]; 51 | } 52 | 53 | System.out.println("Shortest path length is: " + (path.size() - 1)); 54 | 55 | for (int i = path.size() - 1; i >= 0; i--) { 56 | System.out.print(path.get(i) + " "); 57 | } 58 | } 59 | 60 | private static void bfs(List> graph, int source, int destination) { 61 | 62 | Deque queue = new ArrayDeque<>(); 63 | 64 | queue.offer(source); 65 | visited[source] = true; 66 | 67 | while (!queue.isEmpty()) { 68 | int node = queue.poll(); 69 | if (node == destination) { 70 | System.out.println(); 71 | return; 72 | } 73 | for (int child : graph.get(node)) { 74 | if (!visited[child]) { 75 | visited[child] = true; 76 | prevNodes[child] = node; 77 | queue.offer(child); 78 | } 79 | } 80 | } 81 | 82 | } 83 | 84 | public static List> getConnectedComponents(List> graph) { 85 | boolean[] visited = new boolean[graph.size()]; 86 | List> components = new ArrayList<>(); 87 | 88 | for (int start = 0; start < graph.size(); start++) { 89 | if (!visited[start]) { 90 | components.add(new ArrayDeque<>()); 91 | bfs(start, components, graph, visited); 92 | } 93 | } 94 | 95 | return components; 96 | } 97 | 98 | private static void bfs(int start, List> components, List> graph, boolean[] visited) { 99 | Deque queue = new ArrayDeque<>(); 100 | visited[start] = true; 101 | queue.offer(start); 102 | 103 | while (!queue.isEmpty()) { 104 | int node = queue.poll(); 105 | 106 | components.get(components.size() - 1).offer(node); 107 | 108 | for (int child : graph.get(node)) { 109 | if (!visited[child]) { 110 | visited[child] = true; 111 | queue.offer(child); 112 | } 113 | } 114 | } 115 | } 116 | 117 | private static void dfs(int node, List> components, List> graph, boolean[] visited) { 118 | if (!visited[node]) { 119 | visited[node] = true; 120 | for (int child : graph.get(node)) { 121 | dfs(child, components, graph, visited); 122 | } 123 | components.get(components.size() - 1).offer(node); 124 | } 125 | } 126 | 127 | public static List topSort(Map> graph) { 128 | 129 | List sorted = new ArrayList<>(); 130 | 131 | Set visited = new HashSet<>(); 132 | Set detectCycles = new HashSet<>(); 133 | 134 | for (Map.Entry> node : graph.entrySet()) { 135 | dfs(node.getKey(), visited, graph, sorted, detectCycles); 136 | } 137 | 138 | Collections.reverse(sorted); 139 | 140 | return sorted; 141 | } 142 | 143 | public static void dfs(String key, Set visited, Map> graph, List sorted, Set detectCycles) { 144 | if (detectCycles.contains(key)) { 145 | throw new IllegalArgumentException(); 146 | } 147 | if (!visited.contains(key)) { 148 | visited.add(key); 149 | detectCycles.add(key); 150 | for (String child : graph.get(key)) { 151 | dfs(child, visited, graph, sorted, detectCycles); 152 | } 153 | detectCycles.remove(key); 154 | sorted.add(key); 155 | } 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths/TopologicalSort.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | // This includes some additional algorithms and methods 7 | public class TopologicalSort { 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | int n = Integer.parseInt(scanner.nextLine()); 12 | 13 | List> graph = new ArrayList<>(); 14 | 15 | for (int i = 0; i < n; i++) { 16 | String nextLine = scanner.nextLine(); 17 | if (nextLine.trim().equals("")) { 18 | graph.add(new ArrayList<>()); 19 | } else { 20 | List nextNodes = Arrays.stream(nextLine.split("\\s+")) 21 | .map(Integer::parseInt) 22 | .collect(Collectors.toList()); 23 | graph.add(nextNodes); 24 | } 25 | 26 | } 27 | 28 | List> connectedComponents = getConnectedComponents(graph); 29 | 30 | for (Deque connectedComponent : connectedComponents) { 31 | System.out.print("Connected component: "); 32 | for (int integer : connectedComponent) { 33 | System.out.print(integer + " "); 34 | } 35 | System.out.println(); 36 | } 37 | } 38 | 39 | public static List> getConnectedComponents(List> graph) { 40 | boolean[] visited = new boolean[graph.size()]; 41 | List> components = new ArrayList<>(); 42 | 43 | for (int start = 0; start < graph.size(); start++) { 44 | if (!visited[start]) { 45 | components.add(new ArrayDeque<>()); 46 | bfs(start, components, graph, visited); 47 | } 48 | } 49 | 50 | return components; 51 | } 52 | 53 | private static void bfs(int start, List> components, List> graph, boolean[] visited) { 54 | Deque queue = new ArrayDeque<>(); 55 | visited[start] = true; 56 | queue.offer(start); 57 | 58 | while (!queue.isEmpty()) { 59 | int node = queue.poll(); 60 | 61 | components.get(components.size() - 1).offer(node); 62 | 63 | for (int child : graph.get(node)) { 64 | if (!visited[child]) { 65 | visited[child] = true; 66 | queue.offer(child); 67 | } 68 | } 69 | } 70 | } 71 | 72 | private static void dfs(int node, List> components, List> graph, boolean[] visited) { 73 | if (!visited[node]) { 74 | visited[node] = true; 75 | for (int child : graph.get(node)) { 76 | dfs(child, components, graph, visited); 77 | } 78 | components.get(components.size() - 1).offer(node); 79 | } 80 | } 81 | 82 | public static List topSort(Map> graph) { 83 | 84 | List sorted = new ArrayList<>(); 85 | 86 | Set visited = new HashSet<>(); 87 | Set detectCycles = new HashSet<>(); 88 | 89 | for (Map.Entry> node : graph.entrySet()) { 90 | dfs(node.getKey(), visited, graph, sorted, detectCycles); 91 | } 92 | 93 | Collections.reverse(sorted); 94 | 95 | return sorted; 96 | } 97 | 98 | public static void dfs(String key, Set visited, Map> graph, List sorted, Set detectCycles) { 99 | if (detectCycles.contains(key)) { 100 | throw new IllegalArgumentException(); 101 | } 102 | if (!visited.contains(key)) { 103 | visited.add(key); 104 | detectCycles.add(key); 105 | for (String child : graph.get(key)) { 106 | dfs(child, visited, graph, sorted, detectCycles); 107 | } 108 | detectCycles.remove(key); 109 | sorted.add(key); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/AreasInMatrix.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.util.*; 4 | 5 | public class AreasInMatrix { 6 | 7 | public static class Edge { 8 | int[] source; 9 | int[] dest; 10 | 11 | Edge(int sRow, int sCol) { 12 | this.source = new int[]{sRow, sCol}; 13 | } 14 | 15 | public void setDest(int row, int col) { 16 | this.dest = new int[]{row, col}; 17 | } 18 | } 19 | 20 | public static List graph = new ArrayList<>(); 21 | 22 | public static char[][] matrix; 23 | public static boolean[][] visited; 24 | public static boolean[] visitedNode; 25 | 26 | public static void main(String[] args) { 27 | Scanner scanner = new Scanner(System.in); 28 | 29 | int rows = Integer.parseInt(scanner.nextLine()); 30 | 31 | matrix = new char[rows][]; 32 | visited = new boolean[rows][]; 33 | 34 | for (int i = 0; i < rows; i++) { 35 | matrix[i] = scanner.nextLine().toCharArray(); 36 | visited[i] = new boolean[matrix[i].length]; 37 | } 38 | 39 | for (int i = 0; i < matrix.length; i++) { 40 | for (int j = 0; j < matrix[i].length; j++) { 41 | if (!visited[i][j]) { 42 | dfs(i, j, matrix[i][j]); 43 | } 44 | } 45 | } 46 | 47 | visitedNode = new boolean[graph.size()]; 48 | 49 | Map areas = new TreeMap<>(); 50 | 51 | for (int i = 0; i < graph.size(); i++) { 52 | if (!visitedNode[i]) { 53 | Edge edge = graph.get(i); 54 | char key = matrix[edge.source[0]][edge.source[1]]; 55 | areas.putIfAbsent(key, 0); 56 | areas.put(key, areas.get(key) + 1); 57 | bfs(i); 58 | } 59 | } 60 | 61 | System.out.println("Areas: " + areas.values().stream().mapToInt(e -> e).sum()); 62 | 63 | for (Map.Entry entry : areas.entrySet()) { 64 | System.out.println("Letter '" + entry.getKey() + "' -> " + entry.getValue()); 65 | } 66 | } 67 | 68 | private static void bfs(int source) { 69 | Deque queue = new ArrayDeque<>(); 70 | queue.offer(source); 71 | 72 | visitedNode[source] = true; 73 | 74 | while (!queue.isEmpty()) { 75 | int node = queue.poll(); 76 | Edge edge = graph.get(node); 77 | if (edge.dest != null) { 78 | visitedNode[node + 1] = true; 79 | queue.offer(node + 1); 80 | } 81 | } 82 | } 83 | 84 | private static void dfs(int row, int col, char areaSymbol) { 85 | visited[row][col] = true; 86 | 87 | Edge edge = new Edge(row, col); 88 | graph.add(edge); 89 | if (isInBounds(row, col + 1) && !visited[row][col + 1] && matrix[row][col + 1] == areaSymbol) { 90 | graph.get(graph.size() - 1).setDest(row, col + 1); 91 | dfs(row, col + 1, areaSymbol); 92 | } 93 | if (isInBounds(row, col - 1) && !visited[row][col - 1] && matrix[row][col - 1] == areaSymbol) { 94 | graph.get(graph.size() - 1).setDest(row, col - 1); 95 | dfs(row, col - 1, areaSymbol); 96 | } 97 | if (isInBounds(row + 1, col) && !visited[row + 1][col] && matrix[row + 1][col] == areaSymbol) { 98 | graph.get(graph.size() - 1).setDest(row + 1, col); 99 | dfs(row + 1, col, areaSymbol); 100 | } 101 | if (isInBounds(row - 1, col) && !visited[row - 1][col] && matrix[row - 1][col] == areaSymbol) { 102 | graph.get(graph.size() - 1).setDest(row - 1, col); 103 | dfs(row - 1, col, areaSymbol); 104 | } 105 | } 106 | 107 | private static boolean isInBounds(int row, int col) { 108 | return !isOutOfBounds(row, col); 109 | } 110 | 111 | private static boolean isOutOfBounds(int row, int col) { 112 | return row < 0 || row >= matrix.length || col < 0 || col >= matrix[row].length; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/BreakCycles.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | 9 | public class BreakCycles { 10 | private static Map> graph = new HashMap<>(); 11 | private static List removedEdges = new ArrayList<>(); 12 | private static SortedSet outputCycle; 13 | 14 | public static void main(String[] args) throws IOException { 15 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 16 | String line = reader.readLine(); 17 | while (line != null && !line.equals("")) { 18 | String[] node = line.split(" -> "); 19 | String[] edgeParts = node.length > 1 ? node[1].split(" ") : new String[0]; 20 | Set temp = new HashSet<>(); 21 | for (String edge : edgeParts) { 22 | boolean success = temp.add(edge.trim()); 23 | if (!success) { 24 | if (node[0].compareTo(edge) > 0) { 25 | removedEdges.add(String.format("%s - %s", edge, node[0])); 26 | } 27 | } 28 | } 29 | graph.put(node[0], temp); 30 | line = reader.readLine(); 31 | } 32 | 33 | while (true) { 34 | Set visited = new HashSet<>(); 35 | boolean noCycles = true; 36 | for (String node : graph.keySet()) { 37 | SortedSet cycle = new TreeSet<>(); 38 | outputCycle = new TreeSet<>(); 39 | boolean cyclic = searchForCycles(node, visited, cycle, null); 40 | if (cyclic) { 41 | noCycles = false; 42 | breakCycle(); 43 | break; 44 | } 45 | } 46 | if (noCycles) { 47 | break; 48 | } 49 | } 50 | 51 | 52 | System.out.println("Edges to remove: " + removedEdges.size()); 53 | removedEdges = removedEdges.stream().sorted().collect(Collectors.toList()); 54 | for (String edge : removedEdges) { 55 | System.out.println(edge); 56 | } 57 | } 58 | 59 | private static void breakCycle() { 60 | 61 | Map vertexEdges = new HashMap<>(); 62 | for (String node : outputCycle) { 63 | for (String vertex : outputCycle) { 64 | if (graph.get(node).contains(vertex)) { 65 | vertexEdges.putIfAbsent(node, 0); 66 | vertexEdges.put(node, vertexEdges.get(node) + 1); 67 | } 68 | } 69 | } 70 | 71 | while (true) { 72 | boolean hasChanged = false; 73 | for (String node : vertexEdges.keySet()) { 74 | if (vertexEdges.get(node) == 1 && outputCycle.contains(node)) { 75 | outputCycle.remove(node); 76 | hasChanged = true; 77 | break; 78 | } 79 | } 80 | if (!hasChanged) { 81 | break; 82 | } 83 | } 84 | 85 | for (String node : outputCycle) { 86 | for (String vertex : outputCycle) { 87 | if (graph.get(node).contains(vertex)) { 88 | removedEdges.add(String.format("%s - %s", node, vertex)); 89 | graph.get(node).remove(vertex); 90 | graph.get(vertex).remove(node); 91 | return; 92 | } 93 | } 94 | } 95 | } 96 | 97 | private static boolean searchForCycles(String node, Set visited, SortedSet cycle, String parent) { 98 | boolean output = false; 99 | if (cycle.contains(node)) { 100 | outputCycle.addAll(cycle); 101 | return true; 102 | } 103 | if (!visited.contains(node)) { 104 | visited.add(node); 105 | cycle.add(node); 106 | if (graph.containsKey(node)) { 107 | for (String child : graph.get(node)) { 108 | if (!child.equals(parent)) { 109 | output = output || searchForCycles(child, visited, cycle, node); 110 | } 111 | } 112 | cycle.remove(node); 113 | } 114 | } 115 | return output; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/CyclesInGraph.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.util.*; 4 | 5 | public class CyclesInGraph { 6 | 7 | public static Map> graph = new HashMap<>(); 8 | 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | 12 | String line = scanner.nextLine(); 13 | 14 | String source = null; 15 | 16 | while (!line.equals("End")) { 17 | 18 | String[] tokens = line.split("-"); 19 | 20 | if (source == null) { 21 | source = tokens[0]; 22 | } 23 | 24 | graph.putIfAbsent(tokens[0], new ArrayList<>()); 25 | 26 | graph.get(tokens[0]).add(tokens[1]); 27 | 28 | line = scanner.nextLine(); 29 | } 30 | 31 | Set visited = new HashSet<>(); 32 | Set cycles = new HashSet<>(); 33 | String out = ""; 34 | try { 35 | 36 | for (String s : graph.keySet()) { 37 | if (!visited.contains(s)) { 38 | dfs(s, visited, cycles); 39 | out = "Acyclic: Yes"; 40 | } 41 | } 42 | 43 | } catch (IllegalStateException ex) { 44 | out = ex.getMessage(); 45 | } 46 | System.out.println(out); 47 | } 48 | 49 | private static void dfs(String source, Set visited, Set cycles) { 50 | if (cycles.contains(source)) { 51 | throw new IllegalStateException("Acyclic: No"); 52 | } 53 | if (visited.contains(source)) { 54 | return; 55 | } 56 | cycles.add(source); 57 | visited.add(source); 58 | if (graph.get(source) == null) { 59 | return; 60 | } 61 | for (String child : graph.get(source)) { 62 | dfs(child, visited, cycles); 63 | } 64 | cycles.remove(source); 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/DistanceBetween.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.util.*; 4 | 5 | public class DistanceBetween { 6 | public static int[][] graph; 7 | 8 | public static Map indexMapper = new HashMap<>(); 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | int nodes = Integer.parseInt(scanner.nextLine()); 14 | int pairs = Integer.parseInt(scanner.nextLine()); 15 | 16 | graph = new int[nodes + 1][]; 17 | 18 | for (int i = 1; i <= nodes; i++) { 19 | String[] edges = scanner.nextLine() 20 | .split(":"); 21 | 22 | indexMapper.put(Integer.parseInt(edges[0]), i); 23 | 24 | if (edges.length == 1) { 25 | graph[i] = new int[0]; 26 | } else { 27 | graph[i] = Arrays.stream(edges[1] 28 | .split("\\s+")) 29 | .mapToInt(Integer::parseInt) 30 | .toArray(); 31 | } 32 | } 33 | 34 | while (pairs-- > 0) { 35 | int[] relations = Arrays.stream(scanner.nextLine().split("-")) 36 | .mapToInt(Integer::parseInt) 37 | .toArray(); 38 | 39 | int source = relations[0]; 40 | int dest = relations[1]; 41 | 42 | System.out.printf("{%d, %d} -> ", source, dest); 43 | 44 | int[] prev = new int[graph.length]; 45 | 46 | Arrays.fill(prev, -1); 47 | 48 | bfs(graph, indexMapper.get(source), indexMapper.get(dest), prev); 49 | 50 | List path = new ArrayList<>(); 51 | 52 | int parent = prev[indexMapper.get(dest)]; 53 | 54 | while (parent != -1) { 55 | path.add(parent); 56 | parent = prev[parent]; 57 | } 58 | 59 | int size = path.isEmpty() ? -1 : path.size(); 60 | 61 | System.out.println(size); 62 | } 63 | } 64 | 65 | private static void bfs(int[][] graph, int source, int dest, int[] prev) { 66 | 67 | Deque queue = new ArrayDeque<>(); 68 | 69 | queue.offer(source); 70 | 71 | boolean[] visited = new boolean[graph.length + 1]; 72 | visited[source] = true; 73 | 74 | while (!queue.isEmpty()) { 75 | Integer node = queue.poll(); 76 | if (node == dest) { 77 | return; 78 | } 79 | for (int i = 0; i < graph[node].length; i++) { 80 | int child = indexMapper.get(graph[node][i]); 81 | if (!visited[child]) { 82 | prev[child] = node; 83 | visited[child] = true; 84 | queue.offer(child); 85 | } 86 | } 87 | } 88 | 89 | prev[source] = -1; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/RoadReconstruction.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | public class RoadReconstruction { 8 | 9 | private static int[][] graph; 10 | private static StringBuilder output = new StringBuilder(); 11 | private static int time = 0; 12 | private static boolean[] visited; 13 | private static int[] disc; 14 | private static int[] low; 15 | private static int[] parent; 16 | 17 | 18 | public static void main(String[] args) throws IOException { 19 | var reader = new BufferedReader(new InputStreamReader(System.in)); 20 | 21 | int nodes = Integer.parseInt(reader.readLine()); 22 | int edges = Integer.parseInt(reader.readLine()); 23 | 24 | graph = new int[nodes][nodes]; 25 | visited = new boolean[graph.length]; 26 | disc = new int[graph.length]; 27 | low = new int[graph.length]; 28 | parent = new int[graph.length]; 29 | 30 | for (int i = 0; i < edges; i++) { 31 | String[] tokens = reader.readLine().split(" - "); 32 | int from = Integer.parseInt(tokens[0]); 33 | int to = Integer.parseInt(tokens[1]); 34 | graph[from][to] = 1; 35 | graph[to][from] = 1; 36 | } 37 | 38 | bridges(); 39 | 40 | System.out.println("Important streets:"); 41 | System.out.print(output.toString()); 42 | } 43 | 44 | private static void findBridge(int start) { 45 | visited[start] = true; 46 | disc[start] = low[start] = ++time; 47 | 48 | for (int v = 0; v < graph.length; v++) { 49 | if (graph[start][v] != 0) { 50 | if (!visited[v]) { 51 | parent[v] = start; 52 | findBridge(v); 53 | 54 | low[start] = Math.min(low[start], low[v]); 55 | if (low[v] > disc[start]) { 56 | output.append(String.format("%d %d", start, v)).append(System.lineSeparator()); 57 | } 58 | } else if (v != parent[start]) { 59 | low[start] = Math.min(low[start], disc[v]); 60 | } 61 | } 62 | } 63 | } 64 | 65 | private static void bridges() { 66 | 67 | for (int i = 0; i < graph.length; i++) { 68 | parent[i] = -1; 69 | } 70 | 71 | for (int i = 0; i < graph.length; i++) { 72 | if (!visited[i]) { 73 | findBridge(i); 74 | } 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/Salaries.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Scanner; 7 | 8 | public class Salaries { 9 | 10 | public static List> graph = new ArrayList<>(); 11 | 12 | public static long[] salaries; 13 | public static boolean[] visited; 14 | 15 | public static void main(String[] args) { 16 | Scanner scanner = new Scanner(System.in); 17 | 18 | int employees = Integer.parseInt(scanner.nextLine()); 19 | 20 | salaries = new long[employees]; 21 | visited = new boolean[employees]; 22 | 23 | int[] managersCount = new int[employees]; 24 | 25 | for (int i = 0; i < employees; i++) { 26 | graph.add(new ArrayList<>()); 27 | String line = scanner.nextLine(); 28 | 29 | for (int emp = 0; emp < line.length(); emp++) { 30 | char letter = line.charAt(emp); 31 | if (letter == 'Y') { 32 | managersCount[emp]++; 33 | graph.get(i).add(emp); 34 | } 35 | } 36 | } 37 | 38 | List sources = new ArrayList<>(); 39 | 40 | for (int i = 0; i < managersCount.length; i++) { 41 | if (managersCount[i] == 0) { 42 | sources.add(i); 43 | } 44 | } 45 | 46 | for (Integer source : sources) { 47 | dfs(source); 48 | } 49 | 50 | 51 | long sum = Arrays.stream(salaries) 52 | .sum(); 53 | 54 | System.out.println(sum); 55 | } 56 | 57 | private static void dfs(int node) { 58 | if (visited[node]) { 59 | return; 60 | } 61 | 62 | visited[node] = true; 63 | 64 | for (Integer child : graph.get(node)) { 65 | if (!visited[child]) { 66 | dfs(child); 67 | long sum = graph.get(child).stream() 68 | .mapToLong(c -> salaries[c]) 69 | .sum(); 70 | 71 | salaries[child] = sum == 0 ? 1 : sum; 72 | } 73 | } 74 | 75 | long sum = graph.get(node).stream() 76 | .mapToLong(c -> salaries[c]) 77 | .sum(); 78 | 79 | salaries[node] = sum == 0 ? 1 : sum; 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/graph_theory_traversal_and_shortest_paths_exercise/TheMatrix.java: -------------------------------------------------------------------------------- 1 | package graph_theory_traversal_and_shortest_paths_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.Arrays; 7 | 8 | public class TheMatrix { 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 11 | 12 | int[] dimensions = Arrays.stream(reader.readLine().split("\\s+")) 13 | .mapToInt(Integer::parseInt) 14 | .toArray(); 15 | 16 | int row = dimensions[0]; 17 | int col = dimensions[1]; 18 | 19 | char[][] matrix = new char[row][col]; 20 | 21 | for (int i = 0; i < row; i++) { 22 | String[] line = reader.readLine().split("\\s+"); 23 | for (int j = 0; j < line.length; j++) { 24 | matrix[i][j] = line[j].charAt(0); 25 | } 26 | } 27 | 28 | char fillChar = reader.readLine().charAt(0); 29 | 30 | int[] coordinates = Arrays.stream(reader.readLine().split("\\s+")) 31 | .mapToInt(Integer::parseInt) 32 | .toArray(); 33 | 34 | int rowIndex = coordinates[0]; 35 | int colIndex = coordinates[1]; 36 | 37 | char toBeReplaced = matrix[rowIndex][colIndex]; 38 | 39 | replaceCharacters(matrix, fillChar, toBeReplaced, rowIndex, colIndex); 40 | 41 | for (int i = 0; i < row; i++) { 42 | for (int j = 0; j < col; j++) { 43 | System.out.print(matrix[i][j]); 44 | } 45 | System.out.println(); 46 | } 47 | } 48 | 49 | private static void replaceCharacters(char[][] matrix, char fillChar, char toBeReplaced, int row, int col) { 50 | if (isOutOfBounds(matrix, row, col) || matrix[row][col] != toBeReplaced) { 51 | return; 52 | } 53 | matrix[row][col] = fillChar; 54 | 55 | replaceCharacters(matrix, fillChar, toBeReplaced, row + 1, col); 56 | replaceCharacters(matrix, fillChar, toBeReplaced, row - 1, col); 57 | replaceCharacters(matrix, fillChar, toBeReplaced, row, col + 1); 58 | replaceCharacters(matrix, fillChar, toBeReplaced, row, col - 1); 59 | 60 | } 61 | 62 | private static boolean isOutOfBounds(char[][] matrix, int row, int col) { 63 | return row < 0 || col < 0 || row > matrix.length - 1 || col > matrix[0].length - 1; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/BigTrip.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | 9 | public class BigTrip { 10 | 11 | public static List edges = new ArrayList<>(); 12 | public static int[][] graph; 13 | 14 | public static boolean[] visited; 15 | 16 | public static void main(String[] args) throws IOException { 17 | 18 | var reader = new BufferedReader(new InputStreamReader(System.in)); 19 | 20 | int nodes = Integer.parseInt(reader.readLine()); 21 | int e = Integer.parseInt(reader.readLine()); 22 | 23 | graph = new int[nodes + 1][nodes + 1]; 24 | 25 | 26 | for (int i = 0; i < e; i++) { 27 | int[] nextLine = Arrays.stream(reader.readLine().split("\\s+")) 28 | .mapToInt(Integer::parseInt) 29 | .toArray(); 30 | 31 | int source = nextLine[0]; 32 | int dest = nextLine[1]; 33 | int weight = nextLine[2]; 34 | 35 | graph[source][dest] = weight; 36 | edges.add(new int[]{source, dest}); 37 | 38 | } 39 | 40 | int source = Integer.parseInt(reader.readLine()); 41 | int destination = Integer.parseInt(reader.readLine()); 42 | 43 | visited = new boolean[nodes + 1]; 44 | Deque sortedNodes = new ArrayDeque<>(); 45 | 46 | for (int i = 1; i < graph.length; i++) { 47 | topSortDfs(i, sortedNodes); 48 | } 49 | 50 | int[] distances = new int[nodes + 1]; 51 | Arrays.fill(distances, Integer.MIN_VALUE); 52 | distances[source] = 0; 53 | 54 | int[] prev = new int[nodes + 1]; 55 | Arrays.fill(prev, -1); 56 | 57 | for (Integer sortedNode : sortedNodes) { 58 | for (int[] edge : edges) { 59 | int from = edge[0]; 60 | int to = edge[1]; 61 | int weight = graph[from][to]; 62 | if (weight != 0) { 63 | if (distances[from] + weight > distances[to]) { 64 | distances[to] = distances[from] + weight; 65 | prev[to] = from; 66 | } 67 | } 68 | } 69 | } 70 | 71 | List path = new ArrayList<>(); 72 | path.add(destination); 73 | int current = prev[destination]; 74 | while (current != -1) { 75 | path.add(current); 76 | current = prev[current]; 77 | } 78 | Collections.reverse(path); 79 | System.out.println(distances[destination]); 80 | 81 | System.out.println(path.stream().map(String::valueOf).collect(Collectors.joining(" "))); 82 | 83 | } 84 | 85 | private static void topSortDfs(int node, Deque sortedNodes) { 86 | 87 | if (visited[node]) { 88 | return; 89 | } 90 | visited[node] = true; 91 | for (int i = 1; i < graph[node].length; i++) { 92 | if (graph[node][i] != 0) { 93 | topSortDfs(i, sortedNodes); 94 | } 95 | } 96 | 97 | sortedNodes.push(node); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/CableNetwork.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class CableNetwork { 7 | 8 | public static Map> graph = new LinkedHashMap<>(); 9 | 10 | public static int cost = 0; 11 | 12 | public static class Edge implements Comparable { 13 | public int from; 14 | public int to; 15 | public int weight; 16 | 17 | public Edge(int from, int to, int weight) { 18 | this.from = from; 19 | this.to = to; 20 | this.weight = weight; 21 | } 22 | 23 | 24 | @Override 25 | public int compareTo(Edge other) { 26 | return Integer.compare(this.weight, other.weight); 27 | } 28 | } 29 | 30 | public static void main(String[] args) { 31 | Scanner scanner = new Scanner(System.in); 32 | 33 | int budget = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 34 | int nodes = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 35 | int edgeCount = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 36 | 37 | boolean[] connected = new boolean[nodes]; 38 | 39 | for (int i = 0; i < edgeCount; i++) { 40 | String[] tokens = scanner.nextLine().split("\\s+"); 41 | 42 | int from = Integer.parseInt(tokens[0]); 43 | int to = Integer.parseInt(tokens[1]); 44 | int weight = Integer.parseInt(tokens[2]); 45 | 46 | Edge edge = new Edge(from, to, weight); 47 | 48 | graph.putIfAbsent(from, new ArrayList<>()); 49 | graph.get(from).add(edge); 50 | 51 | if (tokens.length == 4) { 52 | connected[from] = connected[to] = true; 53 | } 54 | } 55 | 56 | prim(connected, budget); 57 | 58 | System.out.println("Budget connected: " + cost); 59 | } 60 | 61 | private static boolean prim(boolean[] used, int budget) { 62 | PriorityQueue edges = graph.values() 63 | .stream().flatMap(List::stream) 64 | .filter(e -> (used[e.from] && !used[e.to]) || (!used[e.from] && used[e.to])) 65 | .collect(Collectors.toCollection(PriorityQueue::new)); 66 | 67 | while (!edges.isEmpty()) { 68 | Edge minEdge = edges.poll(); 69 | int from = minEdge.from; 70 | int to = minEdge.to; 71 | int weight = minEdge.weight; 72 | 73 | int removedValue = -1; 74 | 75 | if (used[from] && !used[to]) { 76 | used[to] = true; 77 | removedValue = weight; 78 | } else if (!used[from] && used[to]) { 79 | used[from] = true; 80 | removedValue = weight; 81 | } 82 | 83 | edges = graph.values() 84 | .stream().flatMap(List::stream) 85 | .filter(e -> (used[e.from] && !used[e.to]) || (!used[e.from] && used[e.to])) 86 | .collect(Collectors.toCollection(PriorityQueue::new)); 87 | 88 | if (removedValue != -1 && budget - removedValue > 0) { 89 | budget -= removedValue; 90 | cost += removedValue; 91 | } else if (budget - removedValue < 0) { 92 | return false; 93 | } 94 | } 95 | return true; 96 | } 97 | } -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/CheapTownTour.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class CheapTownTour { 7 | 8 | public static Map> graph = new LinkedHashMap<>(); 9 | 10 | public static int cost = 0; 11 | 12 | public static class Edge implements Comparable { 13 | public int from; 14 | public int to; 15 | public int weight; 16 | 17 | public Edge(int from, int to, int weight) { 18 | this.from = from; 19 | this.to = to; 20 | this.weight = weight; 21 | } 22 | 23 | 24 | @Override 25 | public int compareTo(Edge other) { 26 | return Integer.compare(this.weight, other.weight); 27 | } 28 | } 29 | 30 | public static void main(String[] args) { 31 | Scanner scanner = new Scanner(System.in); 32 | 33 | int nodes = Integer.parseInt(scanner.nextLine()); 34 | int edgeCount = Integer.parseInt(scanner.nextLine()); 35 | 36 | for (int i = 0; i < edgeCount; i++) { 37 | String[] tokens = scanner.nextLine().split(" - "); 38 | 39 | int from = Integer.parseInt(tokens[0]); 40 | int to = Integer.parseInt(tokens[1]); 41 | int weight = Integer.parseInt(tokens[2]); 42 | 43 | Edge edge = new Edge(from, to, weight); 44 | 45 | graph.putIfAbsent(from, new ArrayList<>()); 46 | graph.get(from).add(edge); 47 | } 48 | 49 | int[] parents = new int[nodes]; 50 | 51 | Arrays.fill(parents, -1); 52 | 53 | PriorityQueue edges = graph.values().stream().flatMap(List::stream) 54 | .collect(Collectors.toCollection(PriorityQueue::new)); 55 | 56 | int forestWeight = 0; 57 | 58 | for (int i = 0; i < nodes; i++) { 59 | parents[i] = i; 60 | } 61 | 62 | StringBuilder builder = new StringBuilder(); 63 | 64 | while (!edges.isEmpty()) { 65 | Edge minEdge = edges.poll(); 66 | 67 | int firstRoot = findRoot(minEdge.from, parents); 68 | int secondRoot = findRoot(minEdge.to, parents); 69 | 70 | if (firstRoot != secondRoot) { 71 | forestWeight += minEdge.weight; 72 | parents[secondRoot] = firstRoot; 73 | 74 | for (int i = 0; i < parents.length; i++) { 75 | if (parents[i] == secondRoot) { 76 | parents[i] = firstRoot; 77 | } 78 | } 79 | } 80 | } 81 | 82 | System.out.println("Total cost: " + forestWeight); 83 | } 84 | 85 | private static int findRoot(int node, int[] parents) { 86 | int root = parents[node]; 87 | 88 | while (parents[node] != root) { 89 | root = parents[root]; 90 | } 91 | 92 | return root; 93 | } 94 | } -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/ModifiedKruskal.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class ModifiedKruskal { 7 | 8 | public static Map> graph = new LinkedHashMap<>(); 9 | 10 | public static int cost = 0; 11 | 12 | public static class Edge implements Comparable { 13 | public int from; 14 | public int to; 15 | public int weight; 16 | 17 | public Edge(int from, int to, int weight) { 18 | this.from = from; 19 | this.to = to; 20 | this.weight = weight; 21 | } 22 | 23 | 24 | @Override 25 | public int compareTo(Edge other) { 26 | return Integer.compare(this.weight, other.weight); 27 | } 28 | } 29 | 30 | public static void main(String[] args) { 31 | Scanner scanner = new Scanner(System.in); 32 | 33 | int nodes = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 34 | int edgeCount = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 35 | 36 | boolean[] used = new boolean[nodes]; 37 | 38 | for (int i = 0; i < edgeCount; i++) { 39 | String[] tokens = scanner.nextLine().split("\\s+"); 40 | 41 | int from = Integer.parseInt(tokens[0]); 42 | int to = Integer.parseInt(tokens[1]); 43 | int weight = Integer.parseInt(tokens[2]); 44 | 45 | Edge edge = new Edge(from, to, weight); 46 | 47 | graph.putIfAbsent(from, new ArrayList<>()); 48 | graph.get(from).add(edge); 49 | } 50 | 51 | int[] parents = new int[nodes]; 52 | 53 | Arrays.fill(parents, -1); 54 | 55 | PriorityQueue edges = graph.values().stream().flatMap(List::stream) 56 | .collect(Collectors.toCollection(PriorityQueue::new)); 57 | 58 | int forestWeight = 0; 59 | 60 | for (int i = 0; i < nodes; i++) { 61 | parents[i] = i; 62 | } 63 | 64 | StringBuilder builder = new StringBuilder(); 65 | 66 | while (!edges.isEmpty()) { 67 | Edge minEdge = edges.poll(); 68 | 69 | int firstRoot = findRoot(minEdge.from, parents); 70 | int secondRoot = findRoot(minEdge.to, parents); 71 | 72 | if (firstRoot != secondRoot) { 73 | builder.append(String.format("(%d %d) -> %d%n", minEdge.from, minEdge.to, minEdge.weight)); 74 | forestWeight += minEdge.weight; 75 | parents[secondRoot] = firstRoot; 76 | 77 | for (int i = 0; i < parents.length; i++) { 78 | if (parents[i] == secondRoot) { 79 | parents[i] = firstRoot; 80 | } 81 | } 82 | } 83 | } 84 | 85 | System.out.println("Minimum spanning forest weight: " + forestWeight); 86 | 87 | // System.out.println(builder.toString().trim()); 88 | } 89 | 90 | private static int findRoot(int node, int[] parents) { 91 | int root = parents[node]; 92 | 93 | while (parents[node] != root) { 94 | root = parents[root]; 95 | } 96 | 97 | return root; 98 | } 99 | } -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/MostReliablePath.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.util.*; 4 | 5 | public class MostReliablePath { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int nodes = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 10 | 11 | String[] path = scanner.nextLine().split("\\s+"); 12 | 13 | int edges = Integer.parseInt(scanner.nextLine().split("\\s+")[1]); 14 | 15 | int source = Integer.parseInt(path[1]); 16 | int destination = Integer.parseInt(path[3]); 17 | 18 | 19 | int[][] graph = new int[nodes][nodes]; 20 | 21 | for (int i = 0; i < edges; i++) { 22 | int[] tokens = Arrays.stream(scanner.nextLine().split("\\s+")) 23 | .mapToInt(Integer::parseInt) 24 | .toArray(); 25 | 26 | graph[tokens[0]][tokens[1]] = tokens[2]; 27 | graph[tokens[1]][tokens[0]] = tokens[2]; 28 | } 29 | 30 | double[] distances = new double[nodes]; 31 | boolean[] visited = new boolean[nodes]; 32 | 33 | int[] prev = new int[nodes]; 34 | 35 | Arrays.fill(prev, -1); 36 | 37 | distances[source] = 100.00; 38 | 39 | PriorityQueue queue = new PriorityQueue<>((f, s) -> Double.compare(distances[s], distances[f])); 40 | 41 | queue.offer(source); 42 | 43 | while (!queue.isEmpty()) { 44 | int minNode = queue.poll(); 45 | 46 | visited[minNode] = true; 47 | 48 | for (int i = 0; i < graph[minNode].length; i++) { 49 | int weight = graph[minNode][i]; 50 | if (weight != 0 && !visited[i]) { 51 | 52 | double newDistance = distances[minNode] * weight / 100.00; 53 | 54 | if (newDistance > distances[i]) { 55 | distances[i] = newDistance; 56 | prev[i] = minNode; 57 | } 58 | queue.offer(i); 59 | } 60 | } 61 | } 62 | 63 | System.out.printf("Most reliable path reliability: %.2f%%%n", distances[destination]); 64 | 65 | Deque stack = new ArrayDeque<>(); 66 | 67 | stack.push(destination); 68 | 69 | int node = prev[destination]; 70 | 71 | while (node != -1) { 72 | stack.push(node); 73 | node = prev[node]; 74 | } 75 | 76 | while (!stack.isEmpty()) { 77 | System.out.print(stack.pop()); 78 | if (stack.size() > 0) { 79 | System.out.print(" -> "); 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_exercise/Undefined.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_exercise; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Scanner; 7 | 8 | public class Undefined { 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | int nodes = Integer.parseInt(scanner.nextLine()); 14 | int edgesCount = Integer.parseInt(scanner.nextLine()); 15 | 16 | int[][] graph = new int[nodes + 1][nodes + 1]; 17 | List edges = new ArrayList<>(); 18 | 19 | for (int i = 0; i < edgesCount; i++) { 20 | int[] tokens = Arrays.stream(scanner.nextLine().split("\\s+")) 21 | .mapToInt(Integer::parseInt) 22 | .toArray(); 23 | 24 | graph[tokens[0]][tokens[1]] = tokens[2]; 25 | edges.add(new int[]{tokens[0], tokens[1]}); 26 | } 27 | 28 | int[] distances = new int[nodes + 1]; 29 | 30 | 31 | Arrays.fill(distances, Integer.MAX_VALUE); 32 | 33 | int[] prev = new int[nodes + 1]; 34 | 35 | Arrays.fill(prev, -1); 36 | 37 | int source = Integer.parseInt(scanner.nextLine()); 38 | 39 | distances[source] = 0; 40 | 41 | int destination = Integer.parseInt(scanner.nextLine()); 42 | 43 | boolean hasNegativeCycle = false; 44 | 45 | for (int i = 0; i < nodes - 1; i++) { 46 | for (int[] edge : edges) { 47 | int from = edge[0]; 48 | int to = edge[1]; 49 | if (distances[from] != Integer.MAX_VALUE) { 50 | int newDistance = distances[from] + graph[from][to]; 51 | if (newDistance < distances[to]) { 52 | distances[to] = newDistance; 53 | prev[to] = from; 54 | } 55 | } 56 | } 57 | } 58 | 59 | for (int[] edge : edges) { 60 | int from = edge[0]; 61 | int to = edge[1]; 62 | if (distances[from] != Integer.MAX_VALUE) { 63 | int newDistance = distances[from] + graph[from][to]; 64 | if (newDistance < distances[to]) { 65 | hasNegativeCycle = true; 66 | break; 67 | } 68 | } 69 | } 70 | 71 | if (hasNegativeCycle) { 72 | System.out.println("Undefined"); 73 | } else { 74 | List path = new ArrayList<>(); 75 | 76 | path.add(destination); 77 | 78 | int node = prev[destination]; 79 | 80 | while (node != -1) { 81 | path.add(node); 82 | node = prev[node]; 83 | } 84 | 85 | for (int i = path.size() - 1; i >= 0; i--) { 86 | System.out.print(path.get(i) + " "); 87 | } 88 | System.out.println(); 89 | System.out.println(distances[destination]); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_lab/BellmanFord.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_lab; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class BellmanFord { 7 | 8 | public static int[][] graph; 9 | public static int[] distance; 10 | public static int[] prev; 11 | 12 | public static void main(String[] args) { 13 | Scanner scanner = new Scanner(System.in); 14 | 15 | int nodes = Integer.parseInt(scanner.nextLine()); 16 | int edges = Integer.parseInt(scanner.nextLine()); 17 | 18 | graph = new int[nodes + 1][nodes + 1]; 19 | 20 | for (int i = 0; i < edges; i++) { 21 | int[] tokens = Arrays.stream(scanner.nextLine().split("\\s+")) 22 | .mapToInt(Integer::parseInt) 23 | .toArray(); 24 | 25 | int source = tokens[0]; 26 | int destination = tokens[1]; 27 | int weight = tokens[2]; 28 | 29 | graph[source][destination] = weight; 30 | } 31 | 32 | int source = Integer.parseInt(scanner.nextLine()); 33 | int destination = Integer.parseInt(scanner.nextLine()); 34 | 35 | try { 36 | bellmanFord(source); 37 | } catch (IllegalStateException e) { 38 | System.out.println(e.getMessage()); 39 | return; 40 | } 41 | List path = new ArrayList<>(); 42 | 43 | path.add(destination); 44 | 45 | int node = prev[destination]; 46 | 47 | while (node != -1) { 48 | path.add(node); 49 | node = prev[node]; 50 | } 51 | 52 | Collections.reverse(path); 53 | 54 | System.out.println(path.stream().map(String::valueOf) 55 | .collect(Collectors.joining(" "))); 56 | 57 | System.out.println(distance[destination]); 58 | } 59 | 60 | private static void bellmanFord(int sourceNode) { 61 | // Generic Shortest Paths Algo 62 | // 1 Init dist and prev 63 | // set values to dist and prev 64 | 65 | distance = new int[graph.length]; 66 | Arrays.fill(distance, Integer.MAX_VALUE); 67 | prev = new int[graph.length]; 68 | Arrays.fill(prev, -1); 69 | 70 | distance[sourceNode] = 0; 71 | 72 | for (int i = 1; i < graph.length - 1; i++) { 73 | for (int r = 1; r < graph.length; r++) { 74 | for (int c = 1; c < graph[r].length; c++) { 75 | int weight = graph[r][c]; 76 | if (weight != 0) { 77 | int source = r; 78 | int dest = c; 79 | if (distance[source] != Integer.MAX_VALUE) { 80 | int newValue = distance[source] + weight; 81 | if (newValue < distance[dest]) { 82 | distance[dest] = newValue; 83 | prev[dest] = source; 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | 92 | for (int r = 1; r < graph.length; r++) { 93 | for (int c = 1; c < graph[r].length; c++) { 94 | int weight = graph[r][c]; 95 | if (weight != 0) { 96 | int source = r; 97 | int dest = c; 98 | if (distance[source] != Integer.MAX_VALUE) { 99 | int newValue = distance[source] + weight; 100 | if (newValue < distance[dest]) { 101 | throw new IllegalStateException("Negative Cycle Detected"); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/graphs_bellmanFord_longest_path_in_dag_lab/LongestPath.java: -------------------------------------------------------------------------------- 1 | package graphs_bellmanFord_longest_path_in_dag_lab; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Scanner; 6 | 7 | public class LongestPath { 8 | 9 | public static int[][] graph; 10 | public static int[] distance; 11 | public static boolean[] visited; 12 | 13 | public static void main(String[] args) { 14 | Scanner scanner = new Scanner(System.in); 15 | 16 | int nodes = Integer.parseInt(scanner.nextLine()); 17 | int edges = Integer.parseInt(scanner.nextLine()); 18 | 19 | graph = new int[nodes + 1][nodes + 1]; 20 | 21 | for (int i = 0; i < edges; i++) { 22 | int[] tokens = Arrays.stream(scanner.nextLine().split("\\s+")) 23 | .mapToInt(Integer::parseInt) 24 | .toArray(); 25 | 26 | int source = tokens[0]; 27 | int destination = tokens[1]; 28 | int weight = tokens[2]; 29 | 30 | graph[source][destination] = weight; 31 | } 32 | 33 | int source = Integer.parseInt(scanner.nextLine()); 34 | int destination = Integer.parseInt(scanner.nextLine()); 35 | 36 | distance = new int[graph.length]; 37 | visited = new boolean[graph.length]; 38 | 39 | ArrayDeque sorted = new ArrayDeque<>(); 40 | 41 | for (int i = 1; i < graph.length; i++) { 42 | topologicalSort(i, sorted); 43 | } 44 | 45 | while (!sorted.isEmpty()) { 46 | int node = sorted.pop(); 47 | for (int i = 1; i < graph[node].length; i++) { 48 | int weight = graph[node][i]; 49 | if (weight != 0) { 50 | if (distance[node] + weight > distance[i]) { 51 | distance[i] = distance[node] + weight; 52 | } 53 | } 54 | } 55 | } 56 | 57 | System.out.println(distance[destination]); 58 | } 59 | 60 | private static void topologicalSort(int node, ArrayDeque sorted) { 61 | 62 | if (visited[node]) { 63 | return; 64 | } 65 | visited[node] = true; 66 | 67 | for (int i = 1; i < graph[node].length; i++) { 68 | if (graph[node][i] != 0) { 69 | topologicalSort(i, sorted); 70 | } 71 | } 72 | 73 | sorted.push(node); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/dijkstra/Dijkstra.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.dijkstra; 2 | 3 | import java.util.*; 4 | 5 | public class Dijkstra { 6 | 7 | public static List dijkstraAlgorithm(int[][] graph, int sourceNode, int destinationNode) { 8 | 9 | int[] distances = new int[graph.length]; 10 | int[] prev = new int[graph.length]; 11 | 12 | boolean[] visited = new boolean[graph.length]; 13 | 14 | Arrays.fill(distances, Integer.MAX_VALUE); 15 | Arrays.fill(prev, -1); 16 | 17 | distances[sourceNode] = 0; 18 | 19 | PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(node -> distances[node])); 20 | 21 | queue.offer(sourceNode); 22 | 23 | while (!queue.isEmpty()) { 24 | int parent = queue.poll(); 25 | visited[parent] = true; 26 | int[] children = graph[parent]; 27 | 28 | for (int childNode = 0; childNode < children.length; childNode++) { 29 | if (children[childNode] != 0 && !visited[childNode]) { 30 | queue.offer(childNode); 31 | 32 | int newDistance = distances[parent] + graph[parent][childNode]; 33 | 34 | if (newDistance < distances[childNode]) { 35 | distances[childNode] = newDistance; 36 | prev[childNode] = parent; 37 | } 38 | } 39 | } 40 | } 41 | 42 | List path = new ArrayList<>(); 43 | 44 | path.add(destinationNode); 45 | 46 | int n = prev[destinationNode]; 47 | 48 | while (n != -1) { 49 | path.add(n); 50 | n = prev[n]; 51 | } 52 | 53 | Collections.reverse(path); 54 | 55 | return path.size() == 1 ? null : path; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/dijkstra/Edge.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.dijkstra; 2 | 3 | public class Edge implements Comparable { 4 | 5 | private int startNode; 6 | private int endNode; 7 | private int weight; 8 | 9 | public Edge(int startNode, int endNode, int weight) { 10 | this.startNode = startNode; 11 | this.endNode = endNode; 12 | this.weight = weight; 13 | } 14 | 15 | public int getStartNode() { 16 | return this.startNode; 17 | } 18 | 19 | public void setStartNode(int startNode) { 20 | this.startNode = startNode; 21 | } 22 | 23 | public int getEndNode() { 24 | return this.endNode; 25 | } 26 | 27 | public void setEndNode(int endNode) { 28 | this.endNode = endNode; 29 | } 30 | 31 | public int getWeight() { 32 | return this.weight; 33 | } 34 | 35 | public void setWeight(int weight) { 36 | this.weight = weight; 37 | } 38 | 39 | @Override 40 | public int compareTo(Edge o) { 41 | return Integer.compare(this.weight, o.getWeight()); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return String.format("(%s %s) -> %s", this.startNode, this.endNode, this.weight); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/dijkstra/KruskalAlgorithm.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.dijkstra; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class KruskalAlgorithm { 8 | 9 | public static List kruskal(int numberOfVertices, List edges) { 10 | return null; 11 | } 12 | 13 | public static int findRoot(int node, int[] parents) { 14 | return 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/dijkstra/Main.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.dijkstra; 2 | 3 | import java.util.List; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | 9 | } 10 | 11 | private static void printPath(int[][] graph, int sourceNode, int destinationNode) { 12 | System.out.println(String.format("Shortest path [{0} -> {1}]: ", sourceNode, destinationNode)); 13 | 14 | List path = Dijkstra.dijkstraAlgorithm(graph, sourceNode, destinationNode); 15 | 16 | if (path == null) { 17 | System.out.println("no path"); 18 | } else { 19 | int pathLength = 0; 20 | for (int i = 0; i < path.size() - 1; i++) { 21 | pathLength += graph[path.get(i)][path.get(i + 1)]; 22 | } 23 | 24 | System.out.println(String.format("{0} (length {1})", path, pathLength)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/mst/Dijkstra.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.mst; 2 | 3 | import java.util.*; 4 | 5 | public class Dijkstra { 6 | 7 | public static List dijkstraAlgorithm(int[][] graph, int sourceNode, int destinationNode) { 8 | 9 | int[] distances = new int[graph.length]; 10 | int[] prev = new int[graph.length]; 11 | 12 | boolean[] visited = new boolean[graph.length]; 13 | 14 | Arrays.fill(distances, Integer.MAX_VALUE); 15 | Arrays.fill(prev, -1); 16 | 17 | distances[sourceNode] = 0; 18 | 19 | PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(node -> distances[node])); 20 | 21 | queue.offer(sourceNode); 22 | 23 | while (!queue.isEmpty()) { 24 | int parent = queue.poll(); 25 | visited[parent] = true; 26 | int[] children = graph[parent]; 27 | 28 | for (int childNode = 0; childNode < children.length; childNode++) { 29 | if (children[childNode] != 0 && !visited[childNode]) { 30 | queue.offer(childNode); 31 | 32 | int newDistance = distances[parent] + graph[parent][childNode]; 33 | 34 | if (newDistance < distances[childNode]) { 35 | distances[childNode] = newDistance; 36 | prev[childNode] = parent; 37 | } 38 | } 39 | } 40 | } 41 | 42 | List path = new ArrayList<>(); 43 | 44 | path.add(destinationNode); 45 | 46 | int n = prev[destinationNode]; 47 | 48 | while (n != -1) { 49 | path.add(n); 50 | n = prev[n]; 51 | } 52 | 53 | Collections.reverse(path); 54 | 55 | return path.size() == 1 ? null : path; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/mst/Edge.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.mst; 2 | 3 | public class Edge implements Comparable { 4 | 5 | private int startNode; 6 | private int endNode; 7 | private int weight; 8 | 9 | public Edge(int startNode, int endNode, int weight) { 10 | this.startNode = startNode; 11 | this.endNode = endNode; 12 | this.weight = weight; 13 | } 14 | 15 | public int getStartNode() { 16 | return this.startNode; 17 | } 18 | 19 | public void setStartNode(int startNode) { 20 | this.startNode = startNode; 21 | } 22 | 23 | public int getEndNode() { 24 | return this.endNode; 25 | } 26 | 27 | public void setEndNode(int endNode) { 28 | this.endNode = endNode; 29 | } 30 | 31 | public int getWeight() { 32 | return this.weight; 33 | } 34 | 35 | public void setWeight(int weight) { 36 | this.weight = weight; 37 | } 38 | 39 | @Override 40 | public int compareTo(Edge o) { 41 | return Integer.compare(this.weight, o.getWeight()); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return String.format("(%s %s) -> %s", this.startNode, this.endNode, this.weight); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/mst/KruskalAlgorithm.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.mst; 2 | 3 | import java.util.*; 4 | 5 | public class KruskalAlgorithm { 6 | 7 | public static List kruskal(int numberOfVertices, List edges) { 8 | Collections.sort(edges); 9 | 10 | List forest = new ArrayList<>(); 11 | 12 | int[] parents = new int[numberOfVertices]; 13 | 14 | for (int i = 0; i < parents.length; i++) { 15 | parents[i] = i; 16 | } 17 | 18 | while (!edges.isEmpty()) { 19 | Edge edge = edges.remove(0); 20 | 21 | int source = edge.getStartNode(); 22 | int dest = edge.getEndNode(); 23 | 24 | int firstRoot = findRoot(source, parents); 25 | int secondRoot = findRoot(dest, parents); 26 | 27 | if (firstRoot != secondRoot) { 28 | forest.add(edge); 29 | parents[firstRoot] = secondRoot; 30 | } 31 | 32 | } 33 | 34 | return forest; 35 | } 36 | 37 | public static int findRoot(int node, int[] parents) { 38 | 39 | while (parents[node] != node) { 40 | node = parents[node]; 41 | } 42 | 43 | return node; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/graphs_dijkstraI_and_mst_lab/mst/Main.java: -------------------------------------------------------------------------------- 1 | package graphs_dijkstraI_and_mst_lab.mst; 2 | 3 | import java.util.List; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | 9 | } 10 | 11 | private static void printPath(int[][] graph, int sourceNode, int destinationNode) { 12 | System.out.println(String.format("Shortest path [{0} -> {1}]: ", sourceNode, destinationNode)); 13 | 14 | List path = Dijkstra.dijkstraAlgorithm(graph, sourceNode, destinationNode); 15 | 16 | if (path == null) { 17 | System.out.println("no path"); 18 | } else { 19 | int pathLength = 0; 20 | for (int i = 0; i < path.size() - 1; i++) { 21 | pathLength += graph[path.get(i)][path.get(i + 1)]; 22 | } 23 | 24 | System.out.println(String.format("{0} (length {1})", path, pathLength)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_exercise/FindBiConnected.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class FindBiConnected { 10 | private static int[][] graph; 11 | private static int[] lengths; 12 | private static int[] depths; 13 | private static int[] lowPoints; 14 | private static int[] parents; 15 | 16 | private static List> result; 17 | 18 | private static void dfs(int node, int depth, List component) { 19 | depths[node] = depth; 20 | lowPoints[node] = depth; 21 | for (int childIndex = 0; childIndex < lengths[node]; ++childIndex) { 22 | int child = graph[node][childIndex]; 23 | if (depths[child] == 0) {//depth == 0 <=> child is not visited 24 | parents[child] = node; 25 | List childComponent = new ArrayList<>(); 26 | dfs(child, depth + 1, childComponent); 27 | if (lowPoints[child] >= depths[node] || parents[node] == -1) { 28 | childComponent.add(node); 29 | result.add(childComponent); 30 | } else { 31 | component.addAll(childComponent); 32 | } 33 | lowPoints[node] = Math.min(lowPoints[node], lowPoints[child]); 34 | } else if (child != parents[node]) 35 | lowPoints[node] = Math.min(lowPoints[node], depths[child]); 36 | } 37 | component.add(node); 38 | } 39 | 40 | public static void main(String[] args) throws IOException { 41 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 42 | int nodes = Integer.parseInt(bf.readLine().substring("Nodes: ".length())); 43 | int edges = Integer.parseInt(bf.readLine().substring("Edges: ".length())); 44 | graph = new int[nodes][nodes]; 45 | lengths = new int[nodes]; 46 | for (int i = 0; i < edges; ++i) { 47 | String[] tokens = bf.readLine().split(" "); 48 | int startNode = Integer.parseInt(tokens[0]); 49 | int endNode = Integer.parseInt(tokens[1]); 50 | graph[startNode][lengths[startNode]++] = endNode; 51 | graph[endNode][lengths[endNode]++] = startNode; 52 | } 53 | depths = new int[nodes]; 54 | lowPoints = new int[nodes]; 55 | parents = new int[nodes]; 56 | parents[0] = -1; 57 | result = new ArrayList<>(nodes); 58 | dfs(0, 1, new ArrayList<>(nodes)); 59 | 60 | System.out.println("Number of bi-connected components: " + result.size()); 61 | 62 | bf.close(); 63 | } 64 | } -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_exercise/MaximumTasks.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.LinkedList; 7 | import java.util.Queue; 8 | 9 | public class MaximumTasks { 10 | private static boolean[][] graph; 11 | private static int[] parents; 12 | private static int source; 13 | private static int sink; 14 | 15 | private static boolean bfs() { 16 | boolean[] visited = new boolean[graph.length]; 17 | 18 | Queue queue = new LinkedList<>(); 19 | queue.offer(source); 20 | visited[source] = true; 21 | 22 | while (!queue.isEmpty()) { 23 | int node = queue.poll(); 24 | for (int child = graph[node].length - 1; child >= 0; --child) 25 | if (graph[node][child] && !visited[child]) { 26 | visited[child] = true; 27 | parents[child] = node; 28 | queue.offer(child); 29 | } 30 | } 31 | 32 | return visited[sink]; 33 | } 34 | 35 | public static void main(String[] args) throws IOException { 36 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 37 | int persons = Integer.parseInt(bf.readLine().substring("Persons: ".length())); 38 | int tasks = Integer.parseInt(bf.readLine().substring("Tasks: ".length())); 39 | int nodes = persons + tasks + 2;//first persons then tasks 40 | source = nodes - 2;//node before last 41 | sink = nodes - 1;//last node 42 | graph = new boolean[nodes][nodes]; 43 | parents = new int[nodes]; 44 | parents[source] = -1; 45 | //read task/person table 46 | for (int i = 0; i < persons; ++i) { 47 | String line = bf.readLine(); 48 | for (int j = 0; j < tasks; ++j) 49 | if (line.charAt(j) == 'Y') 50 | graph[i][persons + j] = true; 51 | } 52 | //add source to persons edges 53 | for (int i = 0; i < persons; ++i) 54 | graph[source][i] = true; 55 | //add tasks to sink edges 56 | for (int i = 0; i < tasks; ++i) 57 | graph[persons + i][sink] = true; 58 | 59 | //Edmonds-Karp 60 | while (bfs()) { 61 | int node = sink; 62 | while (node != source) { 63 | graph[parents[node]][node] = false; 64 | graph[node][parents[node]] = true; 65 | node = parents[node]; 66 | } 67 | } 68 | 69 | StringBuilder result = new StringBuilder(16384); 70 | for (int i = 0; i < persons; ++i) 71 | for (int j = 0; j < tasks; ++j) 72 | if (graph[persons + j][i])//back edge from j-th task to i-th person, so there is flow there 73 | result.append((char) ('A' + i)).append('-').append(j + 1).append('\n');//j -> j+1, renumber tasks 74 | 75 | System.out.println(result); 76 | 77 | bf.close(); 78 | } 79 | } -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/articulation_points/ArticulationPoints.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.articulation_points; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class ArticulationPoints { 8 | 9 | public static List[] graph; 10 | public static List points; 11 | public static boolean[] visited; 12 | public static int[] parents; 13 | public static int[] depths; 14 | public static int[] lowpoints; 15 | 16 | public static List findArticulationPoints(List[] targetGraph) { 17 | graph = targetGraph; 18 | points = new ArrayList<>(); 19 | visited = new boolean[graph.length]; 20 | parents = new int[graph.length]; 21 | depths = new int[graph.length]; 22 | lowpoints = new int[graph.length]; 23 | 24 | Arrays.fill(parents, -1); 25 | 26 | discoverArticulationPoints(0, 1); 27 | 28 | return points; 29 | } 30 | 31 | private static void discoverArticulationPoints(int node, int depth) { 32 | visited[node] = true; 33 | depths[node] = depth; 34 | lowpoints[node] = depth; 35 | 36 | int children = 0; 37 | 38 | boolean isArticulationPoint = false; 39 | 40 | for (int child : graph[node]) { 41 | if (!visited[child]) { 42 | parents[child] = node; 43 | children++; 44 | discoverArticulationPoints(child, depth + 1); 45 | if (lowpoints[child] >= depth) { 46 | isArticulationPoint = true; 47 | } 48 | lowpoints[node] = Math.min(lowpoints[node], lowpoints[child]); 49 | } else if (parents[node] != child) { 50 | lowpoints[node] = Math.min(lowpoints[node], depths[child]); 51 | } 52 | } 53 | 54 | if ((parents[node] == -1 && children > 1) || 55 | (parents[node] != -1 && isArticulationPoint)) { 56 | points.add(node); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/articulation_points/EdmondsKarp.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.articulation_points; 2 | 3 | public class EdmondsKarp { 4 | public static int findMaxFlow(int[][] targetGraph) { 5 | return -1; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/articulation_points/Main.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.articulation_points; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/articulation_points/StronglyConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.articulation_points; 2 | 3 | import java.util.*; 4 | 5 | public class StronglyConnectedComponents { 6 | 7 | private static List> stronglyConnectedComponents; 8 | private static boolean[] visited; 9 | private static Deque stack = new ArrayDeque<>(); 10 | private static List[] reversedGraph; 11 | private static List[] graph; 12 | 13 | 14 | public static List> findStronglyConnectedComponents(List[] targetGraph) { 15 | graph = targetGraph; 16 | visited = new boolean[graph.length]; 17 | stronglyConnectedComponents = new ArrayList<>(); 18 | 19 | for (int node = 0; node < graph.length; node++) { 20 | if (!visited[node]) { 21 | dfs(node); 22 | } 23 | } 24 | 25 | setReversedGraph(); 26 | 27 | Arrays.fill(visited, false); 28 | 29 | while (!stack.isEmpty()) { 30 | int node = stack.pop(); 31 | 32 | if (!visited[node]) { 33 | stronglyConnectedComponents.add(new ArrayList<>()); 34 | reversedDfs(node); 35 | } 36 | } 37 | 38 | return stronglyConnectedComponents; 39 | } 40 | 41 | private static void reversedDfs(int node) { 42 | if (visited[node]) { 43 | return; 44 | } 45 | 46 | visited[node] = true; 47 | 48 | stronglyConnectedComponents.get(stronglyConnectedComponents.size() - 1).add(node); 49 | 50 | for (int child : reversedGraph[node]) { 51 | reversedDfs(child); 52 | } 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | public static void setReversedGraph() { 57 | reversedGraph = new ArrayList[graph.length]; 58 | 59 | for (int i = 0; i < reversedGraph.length; i++) { 60 | reversedGraph[i] = new ArrayList<>(); 61 | } 62 | 63 | for (int node = 0; node < graph.length; node++) { 64 | for (int child = 0; child < graph[node].size(); child++) { 65 | int parent = graph[node].get(child); 66 | reversedGraph[parent].add(node); 67 | } 68 | } 69 | } 70 | 71 | private static void dfs(int node) { 72 | if (visited[node]) { 73 | return; 74 | } 75 | visited[node] = true; 76 | 77 | for (int child : graph[node]) { 78 | dfs(child); 79 | } 80 | 81 | stack.push(node); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/max_flow/ArticulationPoints.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.max_flow; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class ArticulationPoints { 8 | 9 | public static List[] graph; 10 | public static List points; 11 | public static boolean[] visited; 12 | public static int[] parents; 13 | public static int[] depths; 14 | public static int[] lowpoints; 15 | 16 | public static List findArticulationPoints(List[] targetGraph) { 17 | graph = targetGraph; 18 | points = new ArrayList<>(); 19 | visited = new boolean[graph.length]; 20 | parents = new int[graph.length]; 21 | depths = new int[graph.length]; 22 | lowpoints = new int[graph.length]; 23 | 24 | Arrays.fill(parents, -1); 25 | 26 | discoverArticulationPoints(0, 1); 27 | 28 | return points; 29 | } 30 | 31 | private static void discoverArticulationPoints(int node, int depth) { 32 | visited[node] = true; 33 | depths[node] = depth; 34 | lowpoints[node] = depth; 35 | 36 | int children = 0; 37 | 38 | boolean isArticulationPoint = false; 39 | 40 | for (int child : graph[node]) { 41 | if (!visited[child]) { 42 | parents[child] = node; 43 | children++; 44 | discoverArticulationPoints(child, depth + 1); 45 | if (lowpoints[child] >= depth) { 46 | isArticulationPoint = true; 47 | } 48 | lowpoints[node] = Math.min(lowpoints[node], lowpoints[child]); 49 | } else if (parents[node] != child) { 50 | lowpoints[node] = Math.min(lowpoints[node], depths[child]); 51 | } 52 | } 53 | 54 | if ((parents[node] == -1 && children > 1) || 55 | (parents[node] != -1 && isArticulationPoint)) { 56 | points.add(node); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/max_flow/EdmondsKarp.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.max_flow; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Deque; 6 | 7 | public class EdmondsKarp { 8 | public static int[][] graph; 9 | public static int[] parents; 10 | 11 | public static int findMaxFlow(int[][] targetGraph) { 12 | graph = targetGraph; 13 | parents = new int[graph.length]; 14 | 15 | Arrays.fill(parents, -1); 16 | 17 | int maxFlow = 0; 18 | 19 | while (bfs()) { 20 | int node = graph.length - 1; 21 | int flow = Integer.MAX_VALUE; 22 | while (node != 0) { 23 | flow = Math.min(flow, graph[parents[node]][node]); 24 | node = parents[node]; 25 | } 26 | 27 | maxFlow += flow; 28 | 29 | node = graph.length - 1; 30 | 31 | while (node != 0) { 32 | graph[parents[node]][node] -= flow; 33 | graph[node][parents[node]] += flow; 34 | node = parents[node]; 35 | } 36 | } 37 | 38 | return maxFlow; 39 | } 40 | 41 | private static boolean bfs() { 42 | Deque queue = new ArrayDeque<>(); 43 | boolean[] visited = new boolean[graph.length]; 44 | 45 | Arrays.fill(parents, -1); 46 | 47 | queue.offer(0); 48 | visited[0] = true; 49 | 50 | while (!queue.isEmpty()) { 51 | int node = queue.poll(); 52 | for (int child = 0; child < graph.length; child++) { 53 | if (graph[node][child] > 0 && !visited[child]) { 54 | visited[child] = true; 55 | parents[child] = node; 56 | queue.offer(child); 57 | } 58 | } 59 | } 60 | 61 | return visited[visited.length - 1]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/max_flow/Main.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.max_flow; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/max_flow/StronglyConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.max_flow; 2 | 3 | import java.util.*; 4 | 5 | public class StronglyConnectedComponents { 6 | 7 | private static List> stronglyConnectedComponents; 8 | private static boolean[] visited; 9 | private static Deque stack = new ArrayDeque<>(); 10 | private static List[] reversedGraph; 11 | private static List[] graph; 12 | 13 | 14 | public static List> findStronglyConnectedComponents(List[] targetGraph) { 15 | graph = targetGraph; 16 | visited = new boolean[graph.length]; 17 | stronglyConnectedComponents = new ArrayList<>(); 18 | 19 | for (int node = 0; node < graph.length; node++) { 20 | if (!visited[node]) { 21 | dfs(node); 22 | } 23 | } 24 | 25 | setReversedGraph(); 26 | 27 | Arrays.fill(visited, false); 28 | 29 | while (!stack.isEmpty()) { 30 | int node = stack.pop(); 31 | 32 | if (!visited[node]) { 33 | stronglyConnectedComponents.add(new ArrayList<>()); 34 | reversedDfs(node); 35 | } 36 | } 37 | 38 | return stronglyConnectedComponents; 39 | } 40 | 41 | private static void reversedDfs(int node) { 42 | if (visited[node]) { 43 | return; 44 | } 45 | 46 | visited[node] = true; 47 | 48 | stronglyConnectedComponents.get(stronglyConnectedComponents.size() - 1).add(node); 49 | 50 | for (int child : reversedGraph[node]) { 51 | reversedDfs(child); 52 | } 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | public static void setReversedGraph() { 57 | reversedGraph = new ArrayList[graph.length]; 58 | 59 | for (int i = 0; i < reversedGraph.length; i++) { 60 | reversedGraph[i] = new ArrayList<>(); 61 | } 62 | 63 | for (int node = 0; node < graph.length; node++) { 64 | for (int child = 0; child < graph[node].size(); child++) { 65 | int parent = graph[node].get(child); 66 | reversedGraph[parent].add(node); 67 | } 68 | } 69 | } 70 | 71 | private static void dfs(int node) { 72 | if (visited[node]) { 73 | return; 74 | } 75 | visited[node] = true; 76 | 77 | for (int child : graph[node]) { 78 | dfs(child); 79 | } 80 | 81 | stack.push(node); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/strongly_connected_components/ArticulationPoints.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.strongly_connected_components; 2 | 3 | import java.util.List; 4 | 5 | public class ArticulationPoints { 6 | 7 | public static List findArticulationPoints(List[] targetGraph) { 8 | 9 | return null; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/strongly_connected_components/EdmondsKarp.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.strongly_connected_components; 2 | 3 | public class EdmondsKarp { 4 | public static int findMaxFlow(int[][] targetGraph) { 5 | return -1; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/strongly_connected_components/Main.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.strongly_connected_components; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/graphs_strongly_connected_components_max_flow_lab/strongly_connected_components/StronglyConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package graphs_strongly_connected_components_max_flow_lab.strongly_connected_components; 2 | 3 | import java.util.*; 4 | 5 | public class StronglyConnectedComponents { 6 | 7 | private static List> stronglyConnectedComponents; 8 | private static boolean[] visited; 9 | private static Deque stack = new ArrayDeque<>(); 10 | private static List[] reversedGraph; 11 | private static List[] graph; 12 | 13 | 14 | public static List> findStronglyConnectedComponents(List[] targetGraph) { 15 | graph = targetGraph; 16 | visited = new boolean[graph.length]; 17 | stronglyConnectedComponents = new ArrayList<>(); 18 | 19 | for (int node = 0; node < graph.length; node++) { 20 | if (!visited[node]) { 21 | dfs(node); 22 | } 23 | } 24 | 25 | setReversedGraph(); 26 | 27 | Arrays.fill(visited, false); 28 | 29 | while (!stack.isEmpty()) { 30 | int node = stack.pop(); 31 | 32 | if (!visited[node]) { 33 | stronglyConnectedComponents.add(new ArrayList<>()); 34 | reversedDfs(node); 35 | } 36 | } 37 | 38 | return stronglyConnectedComponents; 39 | } 40 | 41 | private static void reversedDfs(int node) { 42 | if (visited[node]) { 43 | return; 44 | } 45 | 46 | visited[node] = true; 47 | 48 | stronglyConnectedComponents.get(stronglyConnectedComponents.size() - 1).add(node); 49 | 50 | for (int child : reversedGraph[node]) { 51 | reversedDfs(child); 52 | } 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | public static void setReversedGraph() { 57 | reversedGraph = new ArrayList[graph.length]; 58 | 59 | for (int i = 0; i < reversedGraph.length; i++) { 60 | reversedGraph[i] = new ArrayList<>(); 61 | } 62 | 63 | for (int node = 0; node < graph.length; node++) { 64 | for (int child = 0; child < graph[node].size(); child++) { 65 | int parent = graph[node].get(child); 66 | reversedGraph[parent].add(node); 67 | } 68 | } 69 | } 70 | 71 | private static void dfs(int node) { 72 | if (visited[node]) { 73 | return; 74 | } 75 | visited[node] = true; 76 | 77 | for (int child : graph[node]) { 78 | dfs(child); 79 | } 80 | 81 | stack.push(node); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/introduction_to_dynamic_programming_lab/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package introduction_to_dynamic_programming_lab; 2 | 3 | import java.util.Scanner; 4 | 5 | public class Fibonacci { 6 | public static long[] dp; 7 | 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | int n = Integer.parseInt(scanner.nextLine()); 12 | 13 | dp = new long[n + 1]; 14 | 15 | long fib = calcFib(n); 16 | 17 | System.out.println(fib); 18 | } 19 | 20 | private static long calcFib(int n) { 21 | if (n <= 2) { 22 | return 1; 23 | } 24 | 25 | if (dp[n] != 0) { 26 | return dp[n]; 27 | } 28 | 29 | return dp[n] = calcFib(n - 1) + calcFib(n - 2); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/introduction_to_dynamic_programming_lab/LongestIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | package introduction_to_dynamic_programming_lab; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Scanner; 7 | 8 | public class LongestIncreasingSubsequence { 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | 12 | int[] numbers = Arrays.stream(scanner.nextLine().split("\\s+")) 13 | .mapToInt(Integer::parseInt) 14 | .toArray(); 15 | 16 | int[] length = new int[numbers.length]; 17 | int[] prev = new int[numbers.length]; 18 | 19 | Arrays.fill(prev, -1); 20 | 21 | int maxLength = 0, maxIndex = -1; 22 | 23 | for (int i = 0; i < numbers.length; i++) { 24 | int current = numbers[i]; 25 | int bestLength = 1; 26 | int bestIndex = -1; 27 | for (int j = i - 1; j >= 0; j--) { 28 | if (numbers[j] < current && length[j] + 1 >= bestLength) { 29 | bestLength = length[j] + 1; 30 | bestIndex = j; 31 | } 32 | } 33 | prev[i] = bestIndex; 34 | length[i] = bestLength; 35 | if (maxLength < bestLength) { 36 | maxLength = bestLength; 37 | maxIndex = i; 38 | } 39 | } 40 | 41 | List sequence = new ArrayList<>(); 42 | 43 | 44 | int index = maxIndex; 45 | 46 | while (index != -1) { 47 | sequence.add(numbers[index]); 48 | index = prev[index]; 49 | } 50 | 51 | for (int i = sequence.size() - 1; i >= 0; i--) { 52 | System.out.print(sequence.get(i) + " "); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/introduction_to_dynamic_programming_lab/MoveDownRight.java: -------------------------------------------------------------------------------- 1 | package introduction_to_dynamic_programming_lab; 2 | 3 | import java.util.*; 4 | 5 | public class MoveDownRight { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int rows = Integer.parseInt(scanner.nextLine()); 10 | int cols = Integer.parseInt(scanner.nextLine()); 11 | 12 | int[][] elements = new int[rows][cols]; 13 | 14 | for (int row = 0; row < rows; row++) { 15 | elements[row] = Arrays.stream(scanner.nextLine().split("\\s+")) 16 | .mapToInt(Integer::parseInt) 17 | .toArray(); 18 | } 19 | 20 | int[][] table = new int[rows][cols]; 21 | 22 | table[0][0] = elements[0][0]; 23 | 24 | for (int col = 1; col < cols; col++) { 25 | table[0][col] = table[0][col - 1] + elements[0][col]; 26 | } 27 | 28 | for (int row = 1; row < rows; row++) { 29 | table[row][0] = table[row - 1][0] + elements[row][0]; 30 | } 31 | 32 | for (int row = 1; row < rows; row++) { 33 | for (int col = 1; col < cols; col++) { 34 | table[row][col] = Math.max(table[row - 1][col] + elements[row][col], 35 | table[row][col - 1] + elements[row][col]); 36 | } 37 | } 38 | 39 | int row = rows - 1; 40 | int col = cols - 1; 41 | 42 | List path = new ArrayList<>(); 43 | 44 | path.add(formatOutput(row, col)); 45 | 46 | while (row > 0 || col > 0) { 47 | 48 | int top = -1; 49 | 50 | if (row > 0) { 51 | top = table[row - 1][col]; 52 | } 53 | 54 | int left = -1; 55 | 56 | if (col > 0) { 57 | left = table[row][col - 1]; 58 | } 59 | 60 | if (top > left) { 61 | row--; 62 | } else { 63 | col--; 64 | } 65 | 66 | path.add(formatOutput(row, col)); 67 | } 68 | 69 | Collections.reverse(path); 70 | 71 | System.out.println(String.join(" ", path)); 72 | } 73 | 74 | private static String formatOutput(int row, int col) { 75 | return "[" + row + ", " + col + "]"; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/introduction_to_dynamic_programming_lab/RodCutting.java: -------------------------------------------------------------------------------- 1 | package introduction_to_dynamic_programming_lab; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class RodCutting { 7 | 8 | public static int[] bestPrices; 9 | public static int[] prevIndex; 10 | public static int[] prices; 11 | 12 | public static void main(String[] args) { 13 | Scanner scanner = new Scanner(System.in); 14 | 15 | prices = Arrays.stream(scanner.nextLine().split("\\s+")) 16 | .mapToInt(Integer::parseInt) 17 | .toArray(); 18 | 19 | int length = Integer.parseInt(scanner.nextLine()); 20 | 21 | bestPrices = new int[length + 1]; 22 | prevIndex = new int[length + 1]; 23 | 24 | int maxProfit = cutRope(length); 25 | 26 | System.out.println(maxProfit); 27 | 28 | reconstructSolution(length); 29 | } 30 | 31 | private static int cutRope(int length) { 32 | if (length == 0) { 33 | return 0; 34 | } 35 | if (bestPrices[length] != 0) { 36 | return bestPrices[length]; 37 | } 38 | int currentBest = bestPrices[length]; 39 | 40 | for (int i = 1; i <= length; i++) { 41 | currentBest = Math.max(currentBest, prices[i] + cutRope(length - i)); 42 | if (currentBest > bestPrices[length]) { 43 | bestPrices[length] = currentBest; 44 | prevIndex[length] = i; 45 | } 46 | } 47 | 48 | return bestPrices[length]; 49 | } 50 | 51 | private static void reconstructSolution(int length) { 52 | while (length - prevIndex[length] != 0) { 53 | System.out.print(prevIndex[length] + " "); 54 | length = length - prevIndex[length]; 55 | } 56 | System.out.println(prevIndex[length]); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/EightQueensPuzzle.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | public class EightQueensPuzzle { 4 | public static char[][] board = { 5 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 6 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 7 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 8 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 9 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 10 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 11 | {'-', '-', '-', '-', '-', '-', '-', '-',}, 12 | {'-', '-', '-', '-', '-', '-', '-', '-',} 13 | }; 14 | 15 | public static void main(String[] args) { 16 | findQueenPositions(0); 17 | } 18 | 19 | private static void findQueenPositions(int row) { 20 | if (row == 8) { 21 | printSolution(); 22 | return; 23 | } 24 | 25 | for (int col = 0; col < 8; col++) { 26 | if (canPlaceQueen(row, col)) { 27 | putQueen(row, col); 28 | findQueenPositions(row + 1); 29 | removeQueen(row, col); 30 | } 31 | } 32 | } 33 | 34 | private static void removeQueen(int row, int col) { 35 | board[row][col] = '-'; 36 | } 37 | 38 | private static void putQueen(int row, int col) { 39 | board[row][col] = '*'; 40 | } 41 | 42 | private static boolean canPlaceQueen(int row, int col) { 43 | for (int c = 0; c < 8; c++) { 44 | if (board[row][c] == '*') { 45 | return false; 46 | } 47 | } 48 | 49 | for (int r = 0; r < 8; r++) { 50 | if (board[r][col] == '*') { 51 | return false; 52 | } 53 | } 54 | 55 | int r = row, c = col; 56 | 57 | while (r >= 0 && c >= 0) { 58 | if (board[r--][c--] == '*') { 59 | return false; 60 | } 61 | } 62 | 63 | r = row; 64 | c = col; 65 | 66 | while (r < 8 && c < 8) { 67 | if (board[r++][c++] == '*') { 68 | return false; 69 | } 70 | } 71 | 72 | r = row; 73 | c = col; 74 | 75 | while (r >= 0 && c < 8) { 76 | if (board[r--][c++] == '*') { 77 | return false; 78 | } 79 | } 80 | 81 | r = row; 82 | c = col; 83 | 84 | while (r < 8 && c >= 0) { 85 | if (board[r++][c--] == '*') { 86 | return false; 87 | } 88 | } 89 | return true; 90 | } 91 | 92 | 93 | public static void printSolution() { 94 | for (char[] chars : board) { 95 | for (char symbol : chars) { 96 | System.out.print(symbol + " "); 97 | } 98 | System.out.println(); 99 | } 100 | System.out.println(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/GeneratingZeroOneVectors.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.Scanner; 4 | 5 | public class GeneratingZeroOneVectors { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int n = Integer.parseInt(scanner.nextLine()); 10 | 11 | Integer[] memory = new Integer[n]; 12 | 13 | fillVector(memory, 0); 14 | } 15 | 16 | private static void fillVector(Integer[] memory, int index) { 17 | if (index >= memory.length) { 18 | print(memory); 19 | return; 20 | } 21 | 22 | for (int i = 0; i <= 1; i++) { 23 | memory[index] = i; 24 | 25 | fillVector(memory, index + 1); 26 | } 27 | } 28 | 29 | private static void print(Integer[] memory) { 30 | for (Integer integer : memory) { 31 | System.out.print(integer); 32 | } 33 | System.out.println(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/PathsInLabyrinth.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | 7 | public class PathsInLabyrinth { 8 | 9 | static List path = new ArrayList<>(); 10 | 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | 14 | int rows = Integer.parseInt(scanner.nextLine()); 15 | int cols = Integer.parseInt(scanner.nextLine()); 16 | 17 | char[][] labyrinth = new char[rows][cols]; 18 | 19 | for (int row = 0; row < rows; row++) { 20 | labyrinth[row] = scanner.nextLine().toCharArray(); 21 | } 22 | 23 | findPath(labyrinth, 0, 0, ' '); 24 | } 25 | 26 | private static void findPath(char[][] labyrinth, int row, int col, char direction) { 27 | if (!isInBounds(labyrinth, row, col) 28 | || labyrinth[row][col] == 'V' 29 | || labyrinth[row][col] == '*') { 30 | return; 31 | } 32 | 33 | path.add(direction); 34 | 35 | if (labyrinth[row][col] == 'e') { 36 | printPath(); 37 | path.remove(path.size() - 1); 38 | return; 39 | } 40 | 41 | labyrinth[row][col] = 'V'; 42 | 43 | findPath(labyrinth, row - 1, col, 'U'); 44 | findPath(labyrinth, row + 1, col, 'D'); 45 | findPath(labyrinth, row, col - 1, 'L'); 46 | findPath(labyrinth, row, col + 1, 'R'); 47 | 48 | labyrinth[row][col] = '-'; 49 | 50 | path.remove(path.size() - 1); 51 | } 52 | 53 | private static void printPath() { 54 | for (int i = 1; i < path.size(); i++) { 55 | System.out.print(path.get(i)); 56 | } 57 | System.out.println(); 58 | } 59 | 60 | private static boolean isInBounds(char[][] labyrinth, int row, int col) { 61 | return row < labyrinth.length && row >= 0 && col < labyrinth[row].length && col >= 0; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/RecursiveArraySum.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class RecursiveArraySum { 7 | public static void main(String[] args) { 8 | Scanner scanner = new Scanner(System.in); 9 | 10 | int[] arr = Arrays.stream(scanner.nextLine().split("\\s+")) 11 | .mapToInt(Integer::parseInt) 12 | .toArray(); 13 | 14 | int sumTwo = sumNumbers(arr, arr.length - 1); 15 | 16 | System.out.println(sumTwo); 17 | } 18 | 19 | public static int sumNumbers(int[] numbers, int index) { 20 | if (index < 0) { 21 | return 0; 22 | } 23 | 24 | return numbers[index] + sumNumbers(numbers, index - 1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/RecursiveDrawing.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.Scanner; 4 | 5 | public class RecursiveDrawing { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int n = Integer.parseInt(scanner.nextLine()); 10 | 11 | drawFigure(n); 12 | } 13 | 14 | private static void drawFigure(int n) { 15 | if (n == 0) { 16 | return; 17 | } 18 | 19 | for (int i = 0; i < n; i++) { 20 | System.out.print("*"); 21 | } 22 | 23 | System.out.println(); 24 | 25 | drawFigure(n - 1); 26 | 27 | for (int i = 0; i < n; i++) { 28 | System.out.print("#"); 29 | } 30 | 31 | System.out.println(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/RecursiveFactorial.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.Scanner; 4 | 5 | public class RecursiveFactorial { 6 | public static void main(String[] args) { 7 | Scanner scanner = new Scanner(System.in); 8 | 9 | int n = Integer.parseInt(scanner.nextLine()); 10 | 11 | long result = calculateFactorial(n); 12 | 13 | System.out.println(result); 14 | } 15 | 16 | private static long calculateFactorial(int n) { 17 | if (n == 1) { 18 | return 1; 19 | } 20 | 21 | return n * calculateFactorial(n - 1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/recursion_and_backtracking/RecursiveFibonacci.java: -------------------------------------------------------------------------------- 1 | package recursion_and_backtracking; 2 | 3 | import java.util.Scanner; 4 | 5 | public class RecursiveFibonacci { 6 | public static long[] memory; 7 | 8 | public static void main(String[] args) { 9 | int n = Integer.parseInt(new Scanner(System.in).nextLine()); 10 | 11 | memory = new long[n + 1]; 12 | 13 | long fib = fib(n); 14 | 15 | System.out.println(fib); 16 | } 17 | 18 | private static long fib(int n) { 19 | if (n <= 2) { 20 | return 1; 21 | } 22 | 23 | if (memory[n] != 0) { 24 | return memory[n]; 25 | } 26 | 27 | return memory[n] = fib(n - 1) + fib(n - 2); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/Cinema.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | import java.util.stream.Collectors; 7 | 8 | public class Cinema { 9 | public static String[] seats; 10 | public static String[] combinations; 11 | public static boolean[] used; 12 | public static List people; 13 | 14 | public static void main(String[] args) { 15 | Scanner scanner = new Scanner(System.in); 16 | 17 | people = Arrays.stream(scanner.nextLine().split(", ")) 18 | .collect(Collectors.toList()); 19 | 20 | seats = new String[people.size()]; 21 | 22 | String line = scanner.nextLine(); 23 | 24 | while (!line.equals("generate")) { 25 | 26 | String[] tokens = line.split(" - "); 27 | 28 | String name = tokens[0]; 29 | int position = Integer.parseInt(tokens[1]) - 1; 30 | 31 | seats[position] = name; 32 | 33 | people.remove(name); 34 | 35 | line = scanner.nextLine(); 36 | } 37 | 38 | combinations = new String[people.size()]; 39 | used = new boolean[people.size()]; 40 | 41 | permute(0); 42 | } 43 | 44 | private static void permute(int index) { 45 | if (index == combinations.length) { 46 | print(); 47 | return; 48 | } 49 | 50 | for (int i = 0; i < people.size(); i++) { 51 | if (!used[i]) { 52 | used[i] = true; 53 | combinations[index] = people.get(i); 54 | permute(index + 1); 55 | used[i] = false; 56 | } 57 | } 58 | } 59 | 60 | private static void print() { 61 | int index = 0; 62 | String[] out = new String[seats.length]; 63 | for (int i = 0; i < out.length; i++) { 64 | if (seats[i] != null) { 65 | out[i] = seats[i]; 66 | } else { 67 | out[i] = combinations[index++]; 68 | } 69 | } 70 | System.out.println(String.join(" ", out)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/CombinationsWithRepetition.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | public class CombinationsWithRepetition { 8 | public static int[] arr; 9 | public static int n; 10 | 11 | public static void main(String[] args) throws IOException { 12 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 13 | 14 | n = Integer.parseInt(reader.readLine()); 15 | 16 | int k = Integer.parseInt(reader.readLine()); 17 | 18 | arr = new int[k]; 19 | 20 | combinations(0, 1); 21 | } 22 | 23 | private static void combinations(int index, int start) { 24 | if (index == arr.length) { 25 | printArr(); 26 | return; 27 | } 28 | 29 | for (int i = start; i <= n; i++) { 30 | arr[index] = i; 31 | combinations(index + 1, i); 32 | } 33 | } 34 | 35 | private static void printArr() { 36 | for (int n : arr) { 37 | System.out.print(n + " "); 38 | } 39 | System.out.println(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/CombinationsWithoutRepetition.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CombinationsWithoutRepetition { 6 | public static int n; 7 | public static int[] arr; 8 | 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | 12 | n = Integer.parseInt(scanner.nextLine()); 13 | 14 | int k = Integer.parseInt(scanner.nextLine()); 15 | 16 | arr = new int[k]; 17 | 18 | combine(0, 1); 19 | } 20 | 21 | private static void combine(int index, int start) { 22 | if (index == arr.length) { 23 | printArr(); 24 | return; 25 | } 26 | 27 | for (int i = start; i <= n; i++) { 28 | arr[index] = i; 29 | combine(index + 1, i + 1); 30 | } 31 | } 32 | 33 | private static void printArr() { 34 | for (int number : arr) { 35 | System.out.print(number + " "); 36 | } 37 | System.out.println(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/ConnectedAreasInMatrix.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | public class ConnectedAreasInMatrix { 9 | public static char[][] matrix; 10 | public static List areas; 11 | 12 | public static void main(String[] args) { 13 | Scanner scanner = new Scanner(System.in); 14 | 15 | int r = Integer.parseInt(scanner.nextLine()); 16 | int c = Integer.parseInt(scanner.nextLine()); 17 | 18 | matrix = new char[r][c]; 19 | 20 | for (int i = 0; i < r; i++) { 21 | matrix[i] = scanner.nextLine().toCharArray(); 22 | } 23 | 24 | areas = new ArrayList<>(); 25 | 26 | for (int row = 0; row < matrix.length; row++) { 27 | for (int col = 0; col < matrix[row].length; col++) { 28 | if (matrix[row][col] == '-') { 29 | areas.add(new int[]{row, col, 0}); 30 | findAreas(row, col); 31 | } 32 | } 33 | } 34 | 35 | System.out.println("Total areas found: " + areas.size()); 36 | 37 | AtomicInteger counter = new AtomicInteger(1); 38 | 39 | areas.stream() 40 | .sorted((f, s) -> Integer.compare(s[2], f[2])) 41 | .forEach(a -> { 42 | System.out.println("Area #" + counter.getAndIncrement() 43 | + " at (" + a[0] + ", " + a[1] + "), size: " + a[2]); 44 | }); 45 | 46 | } 47 | 48 | private static void findAreas(int row, int col) { 49 | if (isOutOfBounds(row, col) || isNotTraversal(row, col)) { 50 | return; 51 | } 52 | 53 | matrix[row][col] = 'V'; 54 | 55 | areas.get(areas.size() - 1)[2]++; 56 | 57 | findAreas(row + 1, col); 58 | findAreas(row, col + 1); 59 | findAreas(row - 1, col); 60 | findAreas(row, col - 1); 61 | } 62 | 63 | private static boolean isNotTraversal(int row, int col) { 64 | return matrix[row][col] == 'V' || matrix[row][col] == '*'; 65 | } 66 | 67 | private static boolean isOutOfBounds(int row, int col) { 68 | return row < 0 || row >= matrix.length || col < 0 || col >= matrix[row].length; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/NestedLoops.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | public class NestedLoops { 8 | public static int[] arr; 9 | public static int n; 10 | 11 | public static void main(String[] args) throws IOException { 12 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 13 | 14 | n = Integer.parseInt(reader.readLine()); 15 | 16 | arr = new int[n]; 17 | 18 | permute(0); 19 | } 20 | 21 | private static void permute(int index) { 22 | if (index == arr.length) { 23 | printArr(); 24 | return; 25 | } 26 | 27 | for (int i = 1; i <= n; i++) { 28 | arr[index] = i; 29 | permute(index + 1); 30 | } 31 | } 32 | 33 | private static void printArr() { 34 | for (int num : arr) { 35 | System.out.print(num + " "); 36 | } 37 | System.out.println(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/ReverseArray.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | public class ReverseArray { 8 | public static void main(String[] args) throws IOException { 9 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 10 | 11 | String[] elements = reader.readLine().split("\\s+"); 12 | printReversedArray(elements, elements.length - 1); 13 | } 14 | 15 | private static void printReversedArray(String[] elements, int index) { 16 | if (index < 0) { 17 | return; 18 | } 19 | 20 | System.out.print(elements[index] + " "); 21 | printReversedArray(elements, index - 1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/SchoolTeams.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Scanner; 6 | 7 | public class SchoolTeams { 8 | public static String[] girls; 9 | public static String[] girlsCombinations = new String[3]; 10 | public static String[] boys; 11 | public static String[] boysCombinations = new String[2]; 12 | 13 | public static List allGirls = new ArrayList<>(); 14 | public static List allBoys = new ArrayList<>(); 15 | 16 | public static void main(String[] args) { 17 | Scanner scanner = new Scanner(System.in); 18 | 19 | girls = scanner.nextLine().split(", "); 20 | boys = scanner.nextLine().split(", "); 21 | 22 | combineGirls(0, 0); 23 | combineBoys(0, 0); 24 | 25 | for (String allGirl : allGirls) { 26 | for (String allBoy : allBoys) { 27 | System.out.println(allGirl + ", " + allBoy); 28 | } 29 | } 30 | } 31 | 32 | private static void combineGirls(int index, int start) { 33 | if (index == girlsCombinations.length) { 34 | allGirls.add(String.join(", ", girlsCombinations)); 35 | return; 36 | } 37 | 38 | for (int i = start; i < girls.length; i++) { 39 | girlsCombinations[index] = girls[i]; 40 | combineGirls(index + 1, i + 1); 41 | } 42 | } 43 | 44 | private static void combineBoys(int index, int start) { 45 | if (index == boysCombinations.length) { 46 | allBoys.add(String.join(", ", boysCombinations)); 47 | return; 48 | } 49 | 50 | for (int i = start; i < boys.length; i++) { 51 | boysCombinations[index] = boys[i]; 52 | combineBoys(index + 1, i + 1); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/TowersOfHanoi.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayDeque; 7 | import java.util.Comparator; 8 | import java.util.Deque; 9 | import java.util.stream.Collectors; 10 | 11 | public class TowersOfHanoi { 12 | public static StringBuilder out = new StringBuilder(); 13 | 14 | public static Deque source = new ArrayDeque<>(); 15 | public static Deque spare = new ArrayDeque<>(); 16 | public static Deque destination = new ArrayDeque<>(); 17 | 18 | public static int steps = 1; 19 | 20 | public static void main(String[] args) throws IOException { 21 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 22 | 23 | int disk = Integer.parseInt(reader.readLine()); 24 | 25 | for (int i = disk; i >= 1; i--) { 26 | source.push(i); 27 | } 28 | 29 | printRods(); 30 | solve(disk, source, destination, spare); 31 | 32 | System.out.println(out.toString()); 33 | } 34 | 35 | private static void solve(int disk, Deque source, Deque destination, Deque spare) { 36 | if (disk == 1) { 37 | destination.push(source.pop()); 38 | out.append("Step #").append(steps++) 39 | .append(": Moved disk") 40 | .append(System.lineSeparator()); 41 | printRods(); 42 | return; 43 | } 44 | 45 | solve(disk - 1, source, spare, destination); 46 | solve(1, source, destination, spare); 47 | solve(disk - 1, spare, destination, source); 48 | } 49 | 50 | public static void printRods() { 51 | out.append(String.format("Source: %s%nDestination: %s%nSpare: %s%n", 52 | formatRod(source), formatRod(destination), formatRod(spare))) 53 | .append(System.lineSeparator()); 54 | } 55 | 56 | private static String formatRod(Deque stack) { 57 | return stack.stream() 58 | .sorted(Comparator.reverseOrder()) 59 | .map(String::valueOf) 60 | .collect(Collectors.joining(", ")); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/recursion_and_combinatorial_exercise/WordCruncher.java: -------------------------------------------------------------------------------- 1 | package recursion_and_combinatorial_exercise; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class WordCruncher { 7 | public static List words; 8 | public static List combined = new ArrayList<>(); 9 | public static String target; 10 | 11 | public static Set out = new TreeSet<>(); 12 | 13 | public static Map> table = new HashMap<>(); 14 | public static Map occurrences = new HashMap<>(); 15 | 16 | public static void main(String[] args) { 17 | Scanner scanner = new Scanner(System.in); 18 | 19 | words = Arrays.stream(scanner.nextLine().split(", ")) 20 | .collect(Collectors.toList()); 21 | target = scanner.nextLine(); 22 | 23 | words.removeIf(next -> !target.contains(next)); 24 | 25 | for (String substr : words) { 26 | occurrences.putIfAbsent(substr, 0); 27 | occurrences.put(substr, occurrences.get(substr) + 1); 28 | int index = target.indexOf(substr); 29 | while (index != -1) { 30 | table.putIfAbsent(index, new ArrayList<>()); 31 | table.get(index).add(substr); 32 | index = target.indexOf(substr, index + 1); 33 | } 34 | } 35 | permute(0); 36 | 37 | for (String str : out) { 38 | System.out.println(str); 39 | } 40 | } 41 | 42 | private static void permute(int index) { 43 | if (index == target.length()) { 44 | print(); 45 | return; 46 | } 47 | 48 | if (table.containsKey(index)) { 49 | List strings = table.get(index); 50 | for (String str : strings) { 51 | if (occurrences.get(str) > 0) { 52 | occurrences.put(str, occurrences.get(str) - 1); 53 | combined.add(str); 54 | permute(index + str.length()); 55 | combined.remove(combined.size() - 1); 56 | occurrences.put(str, occurrences.get(str) + 1); 57 | } 58 | } 59 | } 60 | } 61 | 62 | private static void print() { 63 | String actual = String.join("", combined); 64 | if (actual.contains(target)) { 65 | out.add(String.join(" ", combined)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/searching_sorting_and_greedy_algorithms/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package searching_sorting_and_greedy_algorithms; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class BinarySearch { 7 | public static void main(String[] args) { 8 | Scanner scanner = new Scanner(System.in); 9 | 10 | int[] arr = Arrays.stream(scanner.nextLine().split("\\s+")) 11 | .mapToInt(Integer::parseInt) 12 | .toArray(); 13 | 14 | int key = Integer.parseInt(scanner.nextLine()); 15 | 16 | System.out.println(indexOf(arr, key)); 17 | } 18 | 19 | private static int indexOf(int[] arr, int key) { 20 | int start = 0; 21 | int end = arr.length - 1; 22 | 23 | while (start <= end) { 24 | int mid = (start + end) / 2; 25 | int curr = arr[mid]; 26 | if (key < curr) { 27 | end = mid - 1; 28 | } else if (key > curr) { 29 | start = mid + 1; 30 | } else { 31 | return mid; 32 | } 33 | } 34 | 35 | return -1; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/searching_sorting_and_greedy_algorithms/MergeSort.java: -------------------------------------------------------------------------------- 1 | package searching_sorting_and_greedy_algorithms; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | public class MergeSort { 7 | 8 | public static int[] counts; 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | 13 | int[] arr = Arrays.stream(scanner.nextLine().split("\\s+")) 14 | .mapToInt(Integer::parseInt) 15 | .toArray(); 16 | 17 | sort(arr); 18 | 19 | StringBuilder builder = new StringBuilder(); 20 | 21 | for (int number : arr) { 22 | builder.append(number).append(" "); 23 | } 24 | System.out.println(builder.toString()); 25 | } 26 | 27 | public static void sort(int[] arr) { 28 | mergeSort(arr, 0, arr.length - 1); 29 | } 30 | 31 | private static void mergeSort(int[] arr, int begin, int end) { 32 | if (begin >= end) { 33 | return; 34 | } 35 | 36 | int mid = (begin + end) / 2; 37 | 38 | mergeSort(arr, begin, mid); 39 | mergeSort(arr, mid + 1, end); 40 | 41 | merge(arr, begin, mid, end); 42 | } 43 | 44 | private static void merge(int[] arr, int begin, int mid, int end) { 45 | if (mid < 0 || mid >= arr.length || arr[mid] < arr[mid + 1]) { 46 | return; 47 | } 48 | 49 | int left = begin; 50 | int right = mid + 1; 51 | 52 | int[] helper = new int[arr.length]; 53 | 54 | for (int i = begin; i <= end; i++) { 55 | helper[i] = arr[i]; 56 | } 57 | 58 | for (int i = begin; i <= end; i++) { 59 | if (left > mid) { 60 | arr[i] = helper[right++]; 61 | } else if (right > end) { 62 | arr[i] = helper[left++]; 63 | } else if (helper[left] < helper[right]) { 64 | arr[i] = helper[left++]; 65 | } else { 66 | arr[i] = helper[right++]; 67 | } 68 | } 69 | } 70 | 71 | private static void swap(int[] arr, int first, int second) { 72 | int temp = arr[first]; 73 | arr[first] = arr[second]; 74 | arr[second] = temp; 75 | } 76 | } -------------------------------------------------------------------------------- /src/searching_sorting_and_greedy_algorithms/QuickSort.java: -------------------------------------------------------------------------------- 1 | package searching_sorting_and_greedy_algorithms; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | import java.util.stream.Collectors; 6 | 7 | public class QuickSort { 8 | 9 | public static void main(String[] args) { 10 | 11 | Scanner scanner = new Scanner(System.in); 12 | int[] arr = Arrays.stream(scanner.nextLine().split("\\s+")) 13 | .mapToInt(Integer::parseInt) 14 | .toArray(); 15 | 16 | quickSort(arr, 0, arr.length - 1); 17 | 18 | String output = Arrays.stream(arr) 19 | .mapToObj(String::valueOf) 20 | .collect(Collectors.joining(" ")); 21 | 22 | System.out.println(output); 23 | } 24 | 25 | private static void quickSort(int[] arr, int left, int right) { 26 | if (left >= right) { 27 | return; 28 | } 29 | 30 | int index = partition(arr, left, right); 31 | quickSort(arr, left, index - 1); 32 | quickSort(arr, index + 1, right); 33 | } 34 | 35 | private static int partition(int[] arr, int left, int right) { 36 | int pivot = arr[right]; 37 | int i = left - 1; 38 | 39 | for (int j = left; j < right; j++) { 40 | if (arr[j] <= pivot) { 41 | i++; 42 | swap(arr, i, j); 43 | } 44 | } 45 | 46 | swap(arr, i + 1, right); 47 | return i + 1; 48 | } 49 | 50 | private static void swap(int[] arr, int i, int j) { 51 | int temp = arr[i]; 52 | arr[i] = arr[j]; 53 | arr[j] = temp; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/searching_sorting_and_greedy_algorithms/SetCover.java: -------------------------------------------------------------------------------- 1 | package searching_sorting_and_greedy_algorithms; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.Set; 10 | import java.util.stream.Collectors; 11 | 12 | import static java.util.Arrays.stream; 13 | 14 | public class SetCover { 15 | 16 | static BufferedReader reader; 17 | 18 | static int[] universe; 19 | 20 | static List sets; 21 | 22 | static List chosenSets; 23 | 24 | public static void main(String[] args) throws IOException { 25 | init(); 26 | chosenSets = chooseSets(sets, universe); 27 | print(); 28 | } 29 | 30 | public static List chooseSets(List sets, int[] universe) { 31 | 32 | List chosen = new ArrayList<>(); 33 | 34 | Set universeAsSet = stream(universe).boxed().collect(Collectors.toSet()); 35 | 36 | while (!universeAsSet.isEmpty()) { 37 | int containedElementsCount = 0; 38 | int[] chosenSet = sets.get(0); 39 | for (int[] set : sets) { 40 | int count = 0; 41 | for (int element : set) { 42 | if (universeAsSet.contains(element)) { 43 | count++; 44 | } 45 | } 46 | 47 | if (containedElementsCount < count) { 48 | containedElementsCount = count; 49 | chosenSet = set; 50 | } 51 | } 52 | chosen.add(chosenSet); 53 | stream(chosenSet).forEach(universeAsSet::remove); 54 | } 55 | 56 | return chosen; 57 | } 58 | 59 | private static void print() { 60 | StringBuilder sb = new StringBuilder(); 61 | sb.append(String.format("Sets to take (%d):%n", chosenSets.size())); 62 | for (int[] set : chosenSets) { 63 | sb.append("{ "); 64 | sb.append(Arrays.toString(set).replaceAll("\\[|]", "")); 65 | sb.append(" }").append(System.lineSeparator()); 66 | } 67 | System.out.println(sb); 68 | } 69 | 70 | private static void init() throws IOException { 71 | reader = new BufferedReader(new InputStreamReader(System.in)); 72 | universe = stream(reader.readLine().substring(10).split(", ")) 73 | .mapToInt(Integer::parseInt).toArray(); 74 | chosenSets = new ArrayList<>(); 75 | sets = new ArrayList<>(); 76 | int numberOfSets = Integer.parseInt(reader.readLine().substring(16)); 77 | for (int i = 0; i < numberOfSets; i++) { 78 | sets.add(stream(reader.readLine().split(", ")) 79 | .mapToInt(Integer::parseInt).toArray()); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/searching_sorting_and_greedy_algorithms/SumOfCoins.java: -------------------------------------------------------------------------------- 1 | package searching_sorting_and_greedy_algorithms; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public class SumOfCoins { 7 | public static void main(String[] args) { 8 | Scanner in = new Scanner(System.in); 9 | 10 | String[] elements = in.nextLine().substring(7).split(", "); 11 | int[] coins = new int[elements.length]; 12 | for (int i = 0; i < coins.length; i++) { 13 | coins[i] = Integer.parseInt(elements[i]); 14 | } 15 | 16 | int targetSum = Integer.parseInt(in.nextLine().substring(5)); 17 | 18 | Map usedCoins = chooseCoins(coins, targetSum); 19 | 20 | for (Map.Entry usedCoin : usedCoins.entrySet()) { 21 | System.out.println(usedCoin.getKey() + " -> " + usedCoin.getValue()); 22 | } 23 | } 24 | 25 | public static Map chooseCoins(int[] coins, int targetSum) { 26 | Map usedCoins = new LinkedHashMap<>(); 27 | 28 | int index = coins.length - 1; 29 | 30 | while (targetSum != 0) { 31 | int coinsToTake = targetSum / coins[index]; 32 | if (coinsToTake != 0) { 33 | usedCoins.put(coins[index], coinsToTake); 34 | } 35 | targetSum %= coins[index]; 36 | index--; 37 | } 38 | 39 | return usedCoins; 40 | } 41 | } --------------------------------------------------------------------------------