Skip to content

Commit d3f4d5b

Browse files
authored
Merge branch 'master' into SMJI/stack/min_max_const_time
2 parents b97057c + 3401c00 commit d3f4d5b

File tree

8 files changed

+465
-0
lines changed

8 files changed

+465
-0
lines changed

DIRECTORY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,11 @@
251251
* divideandconquer
252252
* [BinaryExponentiation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java)
253253
* [ClosestPair](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/ClosestPair.java)
254+
* [CountingInversions](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/CountingInversions.java)
254255
* [MedianOfTwoSortedArrays](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/MedianOfTwoSortedArrays.java)
255256
* [SkylineAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/SkylineAlgorithm.java)
256257
* [StrassenMatrixMultiplication](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/StrassenMatrixMultiplication.java)
258+
* [TilingProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/TilingProblem.java)
257259
* dynamicprogramming
258260
* [BoardPath](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/BoardPath.java)
259261
* [BoundaryFill](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/BoundaryFill.java)
@@ -504,6 +506,7 @@
504506
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
505507
* [HighestResponseRatioNextScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/HighestResponseRatioNextScheduling.java)
506508
* [JobSchedulingWithDeadline](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/JobSchedulingWithDeadline.java)
509+
* [LotteryScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/LotteryScheduling.java)
507510
* [MLFQScheduler](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java)
508511
* [NonPreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/NonPreemptivePriorityScheduling.java)
509512
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
@@ -832,9 +835,11 @@
832835
* divideandconquer
833836
* [BinaryExponentiationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/BinaryExponentiationTest.java)
834837
* [ClosestPairTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/ClosestPairTest.java)
838+
* [CountingInversionsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/CountingInversionsTest.java)
835839
* [MedianOfTwoSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/MedianOfTwoSortedArraysTest.java)
836840
* [SkylineAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/SkylineAlgorithmTest.java)
837841
* [StrassenMatrixMultiplicationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/StrassenMatrixMultiplicationTest.java)
842+
* [TilingProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/TilingProblemTest.java)
838843
* dynamicprogramming
839844
* [BoardPathTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BoardPathTest.java)
840845
* [BoundaryFillTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BoundaryFillTest.java)
@@ -1039,6 +1044,7 @@
10391044
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
10401045
* [HighestResponseRatioNextSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/HighestResponseRatioNextSchedulingTest.java)
10411046
* [JobSchedulingWithDeadlineTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/JobSchedulingWithDeadlineTest.java)
1047+
* [LotterySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/LotterySchedulingTest.java)
10421048
* [MLFQSchedulerTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/MLFQSchedulerTest.java)
10431049
* [NonPreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/NonPreemptivePrioritySchedulingTest.java)
10441050
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
<version>${assertj.version}</version>
4141
<scope>test</scope>
4242
</dependency>
43+
<dependency>
44+
<groupId>org.mockito</groupId>
45+
<artifactId>mockito-core</artifactId>
46+
<version>5.14.1</version>
47+
<scope>test</scope>
48+
</dependency>
49+
4350

4451
<dependency>
4552
<groupId>org.junit.jupiter</groupId>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.thealgorithms.divideandconquer;
2+
3+
/**
4+
* A utility class for counting the number of inversions in an array.
5+
* <p>
6+
* An inversion is a pair (i, j) such that i < j and arr[i] > arr[j].
7+
* This class implements a divide-and-conquer approach, similar to merge sort,
8+
* to count the number of inversions efficiently.
9+
* <p>
10+
* Time Complexity: O(n log n)
11+
* Space Complexity: O(n) (due to temporary arrays during merge step)
12+
*
13+
* <p>Applications:
14+
* - Used in algorithms related to sorting and permutation analysis.
15+
* - Helps in determining how far an array is from being sorted.
16+
* - Applicable in bioinformatics and signal processing.
17+
*
18+
* <p>This class cannot be instantiated, as it is intended to provide
19+
* only static utility methods.
20+
*
21+
* @author Hardvan
22+
*/
23+
public final class CountingInversions {
24+
private CountingInversions() {
25+
}
26+
27+
/**
28+
* Counts the number of inversions in the given array.
29+
*
30+
* @param arr The input array of integers.
31+
* @return The total number of inversions in the array.
32+
*/
33+
public static int countInversions(int[] arr) {
34+
return mergeSortAndCount(arr, 0, arr.length - 1);
35+
}
36+
37+
/**
38+
* Recursively divides the array into two halves, sorts them, and counts
39+
* the number of inversions. Uses a modified merge sort approach.
40+
*
41+
* @param arr The input array.
42+
* @param left The starting index of the current segment.
43+
* @param right The ending index of the current segment.
44+
* @return The number of inversions within the segment [left, right].
45+
*/
46+
private static int mergeSortAndCount(int[] arr, int left, int right) {
47+
if (left >= right) {
48+
return 0;
49+
}
50+
51+
int mid = left + (right - left) / 2;
52+
int inversions = 0;
53+
54+
inversions += mergeSortAndCount(arr, left, mid);
55+
inversions += mergeSortAndCount(arr, mid + 1, right);
56+
inversions += mergeAndCount(arr, left, mid, right);
57+
return inversions;
58+
}
59+
60+
/**
61+
* Merges two sorted subarrays and counts the cross-inversions between them.
62+
* A cross-inversion occurs when an element from the right subarray is
63+
* smaller than an element from the left subarray.
64+
*
65+
* @param arr The input array.
66+
* @param left The starting index of the first subarray.
67+
* @param mid The ending index of the first subarray and midpoint of the segment.
68+
* @param right The ending index of the second subarray.
69+
* @return The number of cross-inversions between the two subarrays.
70+
*/
71+
private static int mergeAndCount(int[] arr, int left, int mid, int right) {
72+
int[] leftArr = new int[mid - left + 1];
73+
int[] rightArr = new int[right - mid];
74+
75+
System.arraycopy(arr, left, leftArr, 0, mid - left + 1);
76+
System.arraycopy(arr, mid + 1, rightArr, 0, right - mid);
77+
78+
int i = 0;
79+
int j = 0;
80+
int k = left;
81+
int inversions = 0;
82+
83+
while (i < leftArr.length && j < rightArr.length) {
84+
if (leftArr[i] <= rightArr[j]) {
85+
arr[k++] = leftArr[i++];
86+
} else {
87+
arr[k++] = rightArr[j++];
88+
inversions += mid + 1 - left - i;
89+
}
90+
}
91+
92+
while (i < leftArr.length) {
93+
arr[k++] = leftArr[i++];
94+
}
95+
while (j < rightArr.length) {
96+
arr[k++] = rightArr[j++];
97+
}
98+
99+
return inversions;
100+
}
101+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package com.thealgorithms.divideandconquer;
2+
3+
/**
4+
* This class provides a solution to the Tiling Problem using divide-and-conquer.
5+
* <p>
6+
* The Tiling Problem involves filling a 2^n x 2^n board with a single missing
7+
* square using L-shaped tiles (each tile covers exactly three squares).
8+
* The algorithm recursively divides the board into four quadrants, places an
9+
* L-shaped tile in the appropriate quadrant, and fills the remaining areas.
10+
*
11+
* <p>Applications:
12+
* - Used in graphics and image processing.
13+
* - Helpful in solving puzzles and tiling problems in competitive programming.
14+
*
15+
* @author Hardvan
16+
*/
17+
public final class TilingProblem {
18+
private TilingProblem() {
19+
}
20+
21+
/**
22+
* A counter used to label the L-shaped tiles placed on the board.
23+
*/
24+
private static int tile = 1;
25+
26+
/**
27+
* A 2D array representing the board to be tiled.
28+
*/
29+
private static int[][] board;
30+
31+
/**
32+
* Solves the tiling problem for a 2^n x 2^n board with one missing square.
33+
*
34+
* @param size The size of the board (must be a power of 2).
35+
* @param missingRow The row index of the missing square.
36+
* @param missingCol The column index of the missing square.
37+
* @return A 2D array representing the tiled board with L-shaped tiles.
38+
*/
39+
public static int[][] solveTiling(int size, int missingRow, int missingCol) {
40+
board = new int[size][size];
41+
fillBoard(size, 0, 0, missingRow, missingCol);
42+
return board;
43+
}
44+
45+
/**
46+
* Recursively fills the board with L-shaped tiles.
47+
*
48+
* <p>The board is divided into four quadrants. Depending on the location of
49+
* the missing square, an L-shaped tile is placed at the center of the board
50+
* to cover three of the four quadrants. The process is then repeated for
51+
* each quadrant until the entire board is filled.
52+
*
53+
* @param size The current size of the sub-board.
54+
* @param row The starting row index of the current sub-board.
55+
* @param col The starting column index of the current sub-board.
56+
* @param missingRow The row index of the missing square within the board.
57+
* @param missingCol The column index of the missing square within the board.
58+
*/
59+
private static void fillBoard(int size, int row, int col, int missingRow, int missingCol) {
60+
if (size == 1) {
61+
return;
62+
}
63+
64+
int half = size / 2;
65+
int t = tile++;
66+
67+
// Top-left quadrant
68+
if (missingRow < row + half && missingCol < col + half) {
69+
fillBoard(half, row, col, missingRow, missingCol);
70+
} else {
71+
board[row + half - 1][col + half - 1] = t;
72+
fillBoard(half, row, col, row + half - 1, col + half - 1);
73+
}
74+
75+
// Top-right quadrant
76+
if (missingRow < row + half && missingCol >= col + half) {
77+
fillBoard(half, row, col + half, missingRow, missingCol);
78+
} else {
79+
board[row + half - 1][col + half] = t;
80+
fillBoard(half, row, col + half, row + half - 1, col + half);
81+
}
82+
83+
// Bottom-left quadrant
84+
if (missingRow >= row + half && missingCol < col + half) {
85+
fillBoard(half, row + half, col, missingRow, missingCol);
86+
} else {
87+
board[row + half][col + half - 1] = t;
88+
fillBoard(half, row + half, col, row + half, col + half - 1);
89+
}
90+
91+
// Bottom-right quadrant
92+
if (missingRow >= row + half && missingCol >= col + half) {
93+
fillBoard(half, row + half, col + half, missingRow, missingCol);
94+
} else {
95+
board[row + half][col + half] = t;
96+
fillBoard(half, row + half, col + half, row + half, col + half);
97+
}
98+
}
99+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.thealgorithms.scheduling;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Random;
6+
7+
/**
8+
* The LotteryScheduling class implements the Lottery Scheduling algorithm, which is
9+
* a probabilistic CPU scheduling algorithm. Processes are assigned tickets, and
10+
* the CPU is allocated to a randomly selected process based on ticket count.
11+
* Processes with more tickets have a higher chance of being selected.
12+
*/
13+
public final class LotteryScheduling {
14+
private LotteryScheduling() {
15+
}
16+
17+
private List<Process> processes;
18+
private Random random;
19+
20+
/**
21+
* Constructs a LotteryScheduling object with the provided list of processes.
22+
*
23+
* @param processes List of processes to be scheduled using Lottery Scheduling.
24+
*/
25+
public LotteryScheduling(final List<Process> processes) {
26+
this.processes = processes;
27+
this.random = new Random();
28+
}
29+
30+
/**
31+
* Constructs a LotteryScheduling object with the provided list of processes and a Random object.
32+
*
33+
* @param processes List of processes to be scheduled using Lottery Scheduling.
34+
* @param random Random object used for generating random numbers.
35+
*/
36+
public LotteryScheduling(final List<Process> processes, Random random) {
37+
this.processes = processes;
38+
this.random = random;
39+
}
40+
41+
/**
42+
* Schedules the processes using the Lottery Scheduling algorithm.
43+
* Each process is assigned a certain number of tickets, and the algorithm randomly
44+
* selects a process to execute based on ticket count. The method calculates the
45+
* waiting time and turnaround time for each process and simulates their execution.
46+
*/
47+
public List<Process> scheduleProcesses() {
48+
int totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
49+
int currentTime = 0;
50+
List<Process> executedProcesses = new ArrayList<>();
51+
52+
while (!processes.isEmpty()) {
53+
int winningTicket = random.nextInt(totalTickets) + 1;
54+
Process selectedProcess = selectProcessByTicket(winningTicket);
55+
56+
if (selectedProcess == null) {
57+
// This should not happen in normal circumstances, but we'll handle it just in case
58+
System.err.println("Error: No process selected. Recalculating total tickets.");
59+
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
60+
continue;
61+
}
62+
63+
selectedProcess.setWaitingTime(currentTime);
64+
currentTime += selectedProcess.getBurstTime();
65+
selectedProcess.setTurnAroundTime(selectedProcess.getWaitingTime() + selectedProcess.getBurstTime());
66+
67+
executedProcesses.add(selectedProcess);
68+
processes.remove(selectedProcess);
69+
70+
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
71+
}
72+
73+
return executedProcesses;
74+
}
75+
76+
/**
77+
* Selects a process based on a winning ticket. The method iterates over the
78+
* list of processes, and as the ticket sum accumulates, it checks if the
79+
* current process holds the winning ticket.
80+
*
81+
* @param winningTicket The randomly generated ticket number that determines the selected process.
82+
* @return The process associated with the winning ticket.
83+
*/
84+
private Process selectProcessByTicket(int winningTicket) {
85+
int ticketSum = 0;
86+
for (Process process : processes) {
87+
ticketSum += process.getTickets();
88+
if (ticketSum >= winningTicket) {
89+
return process;
90+
}
91+
}
92+
return null;
93+
}
94+
95+
/**
96+
* The Process class represents a process in the scheduling system. Each process has
97+
* an ID, burst time (CPU time required for execution), number of tickets (used in
98+
* lottery selection), waiting time, and turnaround time.
99+
*/
100+
public static class Process {
101+
private String processId;
102+
private int burstTime;
103+
private int tickets;
104+
private int waitingTime;
105+
private int turnAroundTime;
106+
107+
public Process(String processId, int burstTime, int tickets) {
108+
this.processId = processId;
109+
this.burstTime = burstTime;
110+
this.tickets = tickets;
111+
}
112+
113+
public String getProcessId() {
114+
return processId;
115+
}
116+
117+
public int getBurstTime() {
118+
return burstTime;
119+
}
120+
121+
public int getTickets() {
122+
return tickets;
123+
}
124+
125+
public int getWaitingTime() {
126+
return waitingTime;
127+
}
128+
129+
public void setWaitingTime(int waitingTime) {
130+
this.waitingTime = waitingTime;
131+
}
132+
133+
public int getTurnAroundTime() {
134+
return turnAroundTime;
135+
}
136+
137+
public void setTurnAroundTime(int turnAroundTime) {
138+
this.turnAroundTime = turnAroundTime;
139+
}
140+
}
141+
}

0 commit comments

Comments
 (0)