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 | }
--------------------------------------------------------------------------------