Skip to content

Commit 5497bb5

Browse files
authored
Merge branch 'master' into refactor/ceil
2 parents 2b6f328 + dba2d86 commit 5497bb5

File tree

12 files changed

+349
-266
lines changed

12 files changed

+349
-266
lines changed
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,48 @@
11
package com.thealgorithms.maths;
22

3-
/*
4-
* Algorithm explanation:
5-
* https://technotip.com/6774/c-program-to-find-generic-root-of-a-number/#:~:text=Generic%20Root%3A%20of%20a%20number,get%20a%20single%2Ddigit%20output.&text=For%20Example%3A%20If%20user%20input,%2B%204%20%2B%205%20%3D%2015.
3+
/**
4+
* Calculates the generic root (repeated digital sum) of a non-negative integer.
5+
* <p>
6+
* For example, the generic root of 12345 is calculated as:
7+
* 1 + 2 + 3 + 4 + 5 = 15,
8+
* then 1 + 5 = 6, so the generic root is 6.
9+
* <p>
10+
* Reference:
11+
* https://technotip.com/6774/c-program-to-find-generic-root-of-a-number/
612
*/
713
public final class GenericRoot {
14+
15+
private static final int BASE = 10;
16+
817
private GenericRoot() {
918
}
1019

11-
private static int base = 10;
12-
20+
/**
21+
* Computes the sum of the digits of a non-negative integer in base 10.
22+
*
23+
* @param n non-negative integer
24+
* @return sum of digits of {@code n}
25+
*/
1326
private static int sumOfDigits(final int n) {
1427
assert n >= 0;
15-
if (n < base) {
28+
if (n < BASE) {
1629
return n;
1730
}
18-
return n % base + sumOfDigits(n / base);
31+
return (n % BASE) + sumOfDigits(n / BASE);
1932
}
2033

34+
/**
35+
* Computes the generic root (repeated digital sum) of an integer.
36+
* For negative inputs, the absolute value is used.
37+
*
38+
* @param n integer input
39+
* @return generic root of {@code n}
40+
*/
2141
public static int genericRoot(final int n) {
22-
if (n < 0) {
23-
return genericRoot(-n);
24-
}
25-
if (n > base) {
26-
return genericRoot(sumOfDigits(n));
42+
int number = Math.abs(n);
43+
if (number < BASE) {
44+
return number;
2745
}
28-
return n;
46+
return genericRoot(sumOfDigits(number));
2947
}
3048
}

src/main/java/com/thealgorithms/misc/RangeInSortedArray.java

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,46 @@
11
package com.thealgorithms.misc;
22

3+
/**
4+
* Utility class for operations to find the range of occurrences of a key
5+
* in a sorted (non-decreasing) array, and to count elements less than or equal to a given key.
6+
*/
37
public final class RangeInSortedArray {
8+
49
private RangeInSortedArray() {
510
}
611

7-
// Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums'
8-
// Gives [-1, -1] in case element doesn't exist in array
12+
/**
13+
* Finds the first and last occurrence indices of the key in a sorted array.
14+
*
15+
* @param nums sorted array of integers (non-decreasing order)
16+
* @param key the target value to search for
17+
* @return int array of size two where
18+
* - index 0 is the first occurrence of key,
19+
* - index 1 is the last occurrence of key,
20+
* or [-1, -1] if the key does not exist in the array.
21+
*/
922
public static int[] sortedRange(int[] nums, int key) {
1023
int[] range = new int[] {-1, -1};
11-
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true);
12-
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false);
24+
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true); // find left boundary
25+
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false); // find right boundary
1326
return range;
1427
}
1528

16-
// Recursive altered binary search which searches for leftmost as well as rightmost occurrence
17-
// of 'key'
29+
/**
30+
* Recursive altered binary search to find either the leftmost or rightmost occurrence of a key.
31+
*
32+
* @param nums the sorted array
33+
* @param key the target to find
34+
* @param left current left bound in search
35+
* @param right current right bound in search
36+
* @param range array to update with boundaries: range[0] for leftmost, range[1] for rightmost
37+
* @param goLeft if true, searches for leftmost occurrence; if false, for rightmost occurrence
38+
*/
1839
public static void alteredBinSearch(int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
1940
if (left > right) {
2041
return;
2142
}
22-
int mid = (left + right) >>> 1;
43+
int mid = left + ((right - left) >>> 1);
2344
if (nums[mid] > key) {
2445
alteredBinSearch(nums, key, left, mid - 1, range, goLeft);
2546
} else if (nums[mid] < key) {
@@ -41,11 +62,19 @@ public static void alteredBinSearch(int[] nums, int key, int left, int right, in
4162
}
4263
}
4364

44-
// Iterative altered binary search which searches for leftmost as well as rightmost occurrence
45-
// of 'key'
65+
/**
66+
* Iterative altered binary search to find either the leftmost or rightmost occurrence of a key.
67+
*
68+
* @param nums the sorted array
69+
* @param key the target to find
70+
* @param left initial left bound
71+
* @param right initial right bound
72+
* @param range array to update with boundaries: range[0] for leftmost, range[1] for rightmost
73+
* @param goLeft if true, searches for leftmost occurrence; if false, for rightmost occurrence
74+
*/
4675
public static void alteredBinSearchIter(int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
4776
while (left <= right) {
48-
final int mid = (left + right) >>> 1;
77+
int mid = left + ((right - left) >>> 1);
4978
if (nums[mid] > key) {
5079
right = mid - 1;
5180
} else if (nums[mid] < key) {
@@ -55,33 +84,48 @@ public static void alteredBinSearchIter(int[] nums, int key, int left, int right
5584
if (mid == 0 || nums[mid - 1] != key) {
5685
range[0] = mid;
5786
return;
58-
} else {
59-
right = mid - 1;
6087
}
88+
right = mid - 1;
6189
} else {
6290
if (mid == nums.length - 1 || nums[mid + 1] != key) {
6391
range[1] = mid;
6492
return;
65-
} else {
66-
left = mid + 1;
6793
}
94+
left = mid + 1;
6895
}
6996
}
7097
}
7198
}
7299

100+
/**
101+
* Counts the number of elements strictly less than the given key.
102+
*
103+
* @param nums sorted array
104+
* @param key the key to compare
105+
* @return the count of elements less than the key
106+
*/
73107
public static int getCountLessThan(int[] nums, int key) {
74108
return getLessThan(nums, key, 0, nums.length - 1);
75109
}
76110

111+
/**
112+
* Helper method using binary search to count elements less than or equal to the key.
113+
*
114+
* @param nums sorted array
115+
* @param key the key to compare
116+
* @param left current left bound
117+
* @param right current right bound
118+
* @return count of elements less than or equal to the key
119+
*/
77120
public static int getLessThan(int[] nums, int key, int left, int right) {
78121
int count = 0;
79122
while (left <= right) {
80-
final int mid = (left + right) >>> 1;
123+
int mid = left + ((right - left) >>> 1);
81124
if (nums[mid] > key) {
82125
right = mid - 1;
83-
} else if (nums[mid] <= key) {
84-
count = mid + 1; // At least mid+1 elements exist which are <= key
126+
} else {
127+
// nums[mid] <= key
128+
count = mid + 1; // all elements from 0 to mid inclusive are <= key
85129
left = mid + 1;
86130
}
87131
}

src/main/java/com/thealgorithms/stacks/InfixToPostfix.java

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,96 @@
44
import java.util.regex.Matcher;
55
import java.util.regex.Pattern;
66

7+
/**
8+
* Utility class for converting an infix arithmetic expression
9+
* into its equivalent postfix (Reverse Polish Notation) form.
10+
* <p>
11+
* This class provides a static method to perform the conversion,
12+
* validating balanced brackets before processing.
13+
* </p>
14+
*/
715
public final class InfixToPostfix {
16+
817
private InfixToPostfix() {
918
}
1019

11-
public static String infix2PostFix(String infixExpression) throws Exception {
20+
/**
21+
* Converts a given infix expression string to a postfix expression string.
22+
* <p>
23+
* The method first checks if the brackets in the input expression are balanced
24+
* by calling {@code BalancedBrackets.isBalanced} on the filtered brackets.
25+
* If the brackets are not balanced, it throws an IllegalArgumentException.
26+
* </p>
27+
* <p>
28+
* Supported operators are: {@code +, -, *, /, ^}
29+
* and operands can be letters or digits.
30+
* </p>
31+
*
32+
* @param infixExpression the arithmetic expression in infix notation
33+
* @return the equivalent postfix notation expression
34+
* @throws IllegalArgumentException if the brackets in the expression are unbalanced
35+
*/
36+
public static String infix2PostFix(String infixExpression) {
1237
if (!BalancedBrackets.isBalanced(filterBrackets(infixExpression))) {
13-
throw new Exception("invalid expression");
38+
throw new IllegalArgumentException("Invalid expression: unbalanced brackets.");
1439
}
40+
1541
StringBuilder output = new StringBuilder();
16-
Stack<Character> stack = new Stack<>();
17-
for (char element : infixExpression.toCharArray()) {
18-
if (Character.isLetterOrDigit(element)) {
19-
output.append(element);
20-
} else if (element == '(') {
21-
stack.push(element);
22-
} else if (element == ')') {
23-
while (!stack.isEmpty() && stack.peek() != '(') {
24-
output.append(stack.pop());
42+
Stack<Character> operatorStack = new Stack<>();
43+
44+
for (char token : infixExpression.toCharArray()) {
45+
if (Character.isLetterOrDigit(token)) {
46+
// Append operands (letters or digits) directly to output
47+
output.append(token);
48+
} else if (token == '(') {
49+
// Push '(' to stack
50+
operatorStack.push(token);
51+
} else if (token == ')') {
52+
// Pop and append until '(' is found
53+
while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
54+
output.append(operatorStack.pop());
2555
}
26-
stack.pop();
56+
operatorStack.pop(); // Remove '(' from stack
2757
} else {
28-
while (!stack.isEmpty() && precedence(element) <= precedence(stack.peek())) {
29-
output.append(stack.pop());
58+
// Pop operators with higher or equal precedence and append them
59+
while (!operatorStack.isEmpty() && precedence(token) <= precedence(operatorStack.peek())) {
60+
output.append(operatorStack.pop());
3061
}
31-
stack.push(element);
62+
operatorStack.push(token);
3263
}
3364
}
34-
while (!stack.isEmpty()) {
35-
output.append(stack.pop());
65+
66+
// Pop any remaining operators
67+
while (!operatorStack.isEmpty()) {
68+
output.append(operatorStack.pop());
3669
}
70+
3771
return output.toString();
3872
}
3973

74+
/**
75+
* Returns the precedence level of the given operator.
76+
*
77+
* @param operator the operator character (e.g., '+', '-', '*', '/', '^')
78+
* @return the precedence value: higher means higher precedence,
79+
* or -1 if the character is not a recognized operator
80+
*/
4081
private static int precedence(char operator) {
41-
switch (operator) {
42-
case '+':
43-
case '-':
44-
return 0;
45-
case '*':
46-
case '/':
47-
return 1;
48-
case '^':
49-
return 2;
50-
default:
51-
return -1;
52-
}
82+
return switch (operator) {
83+
case '+', '-' -> 0;
84+
case '*', '/' -> 1;
85+
case '^' -> 2;
86+
default -> -1;
87+
};
5388
}
5489

90+
/**
91+
* Extracts only the bracket characters from the input string.
92+
* Supports parentheses (), curly braces {}, square brackets [], and angle brackets &lt;&gt;.
93+
*
94+
* @param input the original expression string
95+
* @return a string containing only bracket characters from the input
96+
*/
5597
private static String filterBrackets(String input) {
5698
Pattern pattern = Pattern.compile("[^(){}\\[\\]<>]");
5799
Matcher matcher = pattern.matcher(input);

0 commit comments

Comments
 (0)