Skip to content

Commit 637b85c

Browse files
authored
Merge branch 'master' into aesencryption_add_tests
2 parents 7faa8ac + 26e8ead commit 637b85c

40 files changed

+2739
-207
lines changed

DIRECTORY.md

+29
Large diffs are not rendered by default.

src/main/java/com/thealgorithms/audiofilters/IIRFilter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void setCoeffs(double[] aCoeffs, double[] bCoeffs) throws IllegalArgument
5858
throw new IllegalArgumentException("bCoeffs must be of size " + order + ", got " + bCoeffs.length);
5959
}
6060

61-
for (int i = 0; i <= order; i++) {
61+
for (int i = 0; i < order; i++) {
6262
coeffsA[i] = aCoeffs[i];
6363
coeffsB[i] = bCoeffs[i];
6464
}

src/main/java/com/thealgorithms/backtracking/KnightsTour.java

+73-66
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,26 @@
44
import java.util.Comparator;
55
import java.util.List;
66

7-
/*
8-
* Problem Statement: -
9-
10-
Given a N*N board with the Knight placed on the first block of an empty board. Moving according
11-
to the rules of chess knight must visit each square exactly once. Print the order of each cell in
12-
which they are visited.
13-
14-
Example: -
15-
16-
Input : N = 8
17-
18-
Output:
19-
0 59 38 33 30 17 8 63
20-
37 34 31 60 9 62 29 16
21-
58 1 36 39 32 27 18 7
22-
35 48 41 26 61 10 15 28
23-
42 57 2 49 40 23 6 19
24-
47 50 45 54 25 20 11 14
25-
56 43 52 3 22 13 24 5
26-
51 46 55 44 53 4 21 12
27-
7+
/**
8+
* The KnightsTour class solves the Knight's Tour problem using backtracking.
9+
*
10+
* Problem Statement:
11+
* Given an N*N board with a knight placed on the first block, the knight must
12+
* move according to chess rules and visit each square on the board exactly once.
13+
* The class outputs the sequence of moves for the knight.
14+
*
15+
* Example:
16+
* Input: N = 8 (8x8 chess board)
17+
* Output: The sequence of numbers representing the order in which the knight visits each square.
2818
*/
2919
public final class KnightsTour {
3020
private KnightsTour() {
3121
}
3222

23+
// The size of the chess board (12x12 grid, with 2 extra rows/columns as a buffer around a 8x8 area)
3324
private static final int BASE = 12;
25+
26+
// Possible moves for a knight in chess
3427
private static final int[][] MOVES = {
3528
{1, -2},
3629
{2, -1},
@@ -40,36 +33,40 @@ private KnightsTour() {
4033
{-2, 1},
4134
{-2, -1},
4235
{-1, -2},
43-
}; // Possible moves by knight on chess
44-
private static int[][] grid; // chess grid
45-
private static int total; // total squares in chess
36+
};
37+
38+
// Chess grid representing the board
39+
static int[][] grid;
40+
41+
// Total number of cells the knight needs to visit
42+
static int total;
4643

47-
public static void main(String[] args) {
44+
/**
45+
* Resets the chess board to its initial state.
46+
* Initializes the grid with boundary cells marked as -1 and internal cells as 0.
47+
* Sets the total number of cells the knight needs to visit.
48+
*/
49+
public static void resetBoard() {
4850
grid = new int[BASE][BASE];
4951
total = (BASE - 4) * (BASE - 4);
50-
5152
for (int r = 0; r < BASE; r++) {
5253
for (int c = 0; c < BASE; c++) {
5354
if (r < 2 || r > BASE - 3 || c < 2 || c > BASE - 3) {
54-
grid[r][c] = -1;
55+
grid[r][c] = -1; // Mark boundary cells
5556
}
5657
}
5758
}
58-
59-
int row = 2 + (int) (Math.random() * (BASE - 4));
60-
int col = 2 + (int) (Math.random() * (BASE - 4));
61-
62-
grid[row][col] = 1;
63-
64-
if (solve(row, col, 2)) {
65-
printResult();
66-
} else {
67-
System.out.println("no result");
68-
}
6959
}
7060

71-
// Return True when solvable
72-
private static boolean solve(int row, int column, int count) {
61+
/**
62+
* Recursive method to solve the Knight's Tour problem.
63+
*
64+
* @param row The current row of the knight
65+
* @param column The current column of the knight
66+
* @param count The current move number
67+
* @return True if a solution is found, False otherwise
68+
*/
69+
static boolean solve(int row, int column, int count) {
7370
if (count > total) {
7471
return true;
7572
}
@@ -80,49 +77,72 @@ private static boolean solve(int row, int column, int count) {
8077
return false;
8178
}
8279

80+
// Sort neighbors by Warnsdorff's rule (fewest onward moves)
8381
neighbor.sort(Comparator.comparingInt(a -> a[2]));
8482

8583
for (int[] nb : neighbor) {
86-
row = nb[0];
87-
column = nb[1];
88-
grid[row][column] = count;
89-
if (!orphanDetected(count, row, column) && solve(row, column, count + 1)) {
84+
int nextRow = nb[0];
85+
int nextCol = nb[1];
86+
grid[nextRow][nextCol] = count;
87+
if (!orphanDetected(count, nextRow, nextCol) && solve(nextRow, nextCol, count + 1)) {
9088
return true;
9189
}
92-
grid[row][column] = 0;
90+
grid[nextRow][nextCol] = 0; // Backtrack
9391
}
9492

9593
return false;
9694
}
9795

98-
// Returns List of neighbours
99-
private static List<int[]> neighbors(int row, int column) {
96+
/**
97+
* Returns a list of valid neighboring cells where the knight can move.
98+
*
99+
* @param row The current row of the knight
100+
* @param column The current column of the knight
101+
* @return A list of arrays representing valid moves, where each array contains:
102+
* {nextRow, nextCol, numberOfPossibleNextMoves}
103+
*/
104+
static List<int[]> neighbors(int row, int column) {
100105
List<int[]> neighbour = new ArrayList<>();
101106

102107
for (int[] m : MOVES) {
103108
int x = m[0];
104109
int y = m[1];
105-
if (grid[row + y][column + x] == 0) {
110+
if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid[row + y][column + x] == 0) {
106111
int num = countNeighbors(row + y, column + x);
107112
neighbour.add(new int[] {row + y, column + x, num});
108113
}
109114
}
110115
return neighbour;
111116
}
112117

113-
// Returns the total count of neighbors
114-
private static int countNeighbors(int row, int column) {
118+
/**
119+
* Counts the number of possible valid moves for a knight from a given position.
120+
*
121+
* @param row The row of the current position
122+
* @param column The column of the current position
123+
* @return The number of valid neighboring moves
124+
*/
125+
static int countNeighbors(int row, int column) {
115126
int num = 0;
116127
for (int[] m : MOVES) {
117-
if (grid[row + m[1]][column + m[0]] == 0) {
128+
int x = m[0];
129+
int y = m[1];
130+
if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid[row + y][column + x] == 0) {
118131
num++;
119132
}
120133
}
121134
return num;
122135
}
123136

124-
// Returns true if it is orphan
125-
private static boolean orphanDetected(int count, int row, int column) {
137+
/**
138+
* Detects if moving to a given position will create an orphan (a position with no further valid moves).
139+
*
140+
* @param count The current move number
141+
* @param row The row of the current position
142+
* @param column The column of the current position
143+
* @return True if an orphan is detected, False otherwise
144+
*/
145+
static boolean orphanDetected(int count, int row, int column) {
126146
if (count < total - 1) {
127147
List<int[]> neighbor = neighbors(row, column);
128148
for (int[] nb : neighbor) {
@@ -133,17 +153,4 @@ private static boolean orphanDetected(int count, int row, int column) {
133153
}
134154
return false;
135155
}
136-
137-
// Prints the result grid
138-
private static void printResult() {
139-
for (int[] row : grid) {
140-
for (int i : row) {
141-
if (i == -1) {
142-
continue;
143-
}
144-
System.out.printf("%2d ", i);
145-
}
146-
System.out.println();
147-
}
148-
}
149156
}

src/main/java/com/thealgorithms/backtracking/WordSearch.java

+61-31
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,72 @@
11
package com.thealgorithms.backtracking;
22

3-
/*
4-
Word Search Problem (https://en.wikipedia.org/wiki/Word_search)
5-
6-
Given an m x n grid of characters board and a string word, return true if word exists in the grid.
7-
8-
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are
9-
those horizontally or vertically neighboring. The same letter cell may not be used more than once.
10-
11-
For example,
12-
Given board =
13-
14-
[
15-
['A','B','C','E'],
16-
['S','F','C','S'],
17-
['A','D','E','E']
18-
]
19-
word = "ABCCED", -> returns true,
20-
word = "SEE", -> returns true,
21-
word = "ABCB", -> returns false.
22-
*/
23-
24-
/*
25-
Solution
26-
Depth First Search in matrix (as multiple sources possible) with backtracking
27-
like finding cycle in a directed graph. Maintain a record of path
28-
29-
Tx = O(m * n * 3^L): for each cell, we look at 3 options (not 4 as that one will be visited), we
30-
do it L times Sx = O(L) : stack size is max L
31-
*/
32-
3+
/**
4+
* Word Search Problem
5+
*
6+
* This class solves the word search problem where given an m x n grid of characters (board)
7+
* and a target word, the task is to check if the word exists in the grid.
8+
* The word can be constructed from sequentially adjacent cells (horizontally or vertically),
9+
* and the same cell may not be used more than once in constructing the word.
10+
*
11+
* Example:
12+
* - For board =
13+
* [
14+
* ['A','B','C','E'],
15+
* ['S','F','C','S'],
16+
* ['A','D','E','E']
17+
* ]
18+
* and word = "ABCCED", -> returns true
19+
* and word = "SEE", -> returns true
20+
* and word = "ABCB", -> returns false
21+
*
22+
* Solution:
23+
* - Depth First Search (DFS) with backtracking is used to explore possible paths from any cell
24+
* matching the first letter of the word. DFS ensures that we search all valid paths, while
25+
* backtracking helps in reverting decisions when a path fails to lead to a solution.
26+
*
27+
* Time Complexity: O(m * n * 3^L)
28+
* - m = number of rows in the board
29+
* - n = number of columns in the board
30+
* - L = length of the word
31+
* - For each cell, we look at 3 possible directions (since we exclude the previously visited direction),
32+
* and we do this for L letters.
33+
*
34+
* Space Complexity: O(L)
35+
* - Stack space for the recursive DFS function, where L is the maximum depth of recursion (length of the word).
36+
*/
3337
public class WordSearch {
3438
private final int[] dx = {0, 0, 1, -1};
3539
private final int[] dy = {1, -1, 0, 0};
3640
private boolean[][] visited;
3741
private char[][] board;
3842
private String word;
3943

44+
/**
45+
* Checks if the given (x, y) coordinates are valid positions in the board.
46+
*
47+
* @param x The row index.
48+
* @param y The column index.
49+
* @return True if the coordinates are within the bounds of the board; false otherwise.
50+
*/
4051
private boolean isValid(int x, int y) {
4152
return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
4253
}
4354

55+
/**
56+
* Performs Depth First Search (DFS) from the cell (x, y)
57+
* to search for the next character in the word.
58+
*
59+
* @param x The current row index.
60+
* @param y The current column index.
61+
* @param nextIdx The index of the next character in the word to be matched.
62+
* @return True if a valid path is found to match the remaining characters of the word; false otherwise.
63+
*/
4464
private boolean doDFS(int x, int y, int nextIdx) {
4565
visited[x][y] = true;
4666
if (nextIdx == word.length()) {
4767
return true;
4868
}
69+
4970
for (int i = 0; i < 4; ++i) {
5071
int xi = x + dx[i];
5172
int yi = y + dy[i];
@@ -56,10 +77,19 @@ private boolean doDFS(int x, int y, int nextIdx) {
5677
}
5778
}
5879
}
59-
visited[x][y] = false;
80+
81+
visited[x][y] = false; // Backtrack
6082
return false;
6183
}
6284

85+
/**
86+
* Main function to check if the word exists in the board. It initiates DFS from any
87+
* cell that matches the first character of the word.
88+
*
89+
* @param board The 2D grid of characters (the board).
90+
* @param word The target word to search for in the board.
91+
* @return True if the word exists in the board; false otherwise.
92+
*/
6393
public boolean exist(char[][] board, String word) {
6494
this.board = board;
6595
this.word = word;

src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java

+28
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,32 @@ public long countSetBits(long num) {
4848
}
4949
return cnt;
5050
}
51+
52+
/**
53+
* This approach takes O(1) running time to count the set bits, but requires a pre-processing.
54+
*
55+
* So, we divide our 32-bit input into 8-bit chunks, with four chunks. We have 8 bits in each chunk.
56+
*
57+
* Then the range is from 0-255 (0 to 2^7).
58+
* So, we may need to count set bits from 0 to 255 in individual chunks.
59+
*
60+
* @param num takes a long number
61+
* @return the count of set bits in the binary equivalent
62+
*/
63+
public int lookupApproach(int num) {
64+
int[] table = new int[256];
65+
table[0] = 0;
66+
67+
for (int i = 1; i < 256; i++) {
68+
table[i] = (i & 1) + table[i >> 1]; // i >> 1 equals to i/2
69+
}
70+
71+
int res = 0;
72+
for (int i = 0; i < 4; i++) {
73+
res += table[num & 0xff];
74+
num >>= 8;
75+
}
76+
77+
return res;
78+
}
5179
}

0 commit comments

Comments
 (0)