cleanup: Improve docs, safety, and readability in RangeInSortedArray (#6361)

* cleanup: Improve docs, safety, and readability in RangeInSortedArray

* formatting: fix comment formatting issue

* formatting: fix array formatting issue

---------

Co-authored-by: Deniz Altunkapan <93663085+DenizAltunkapan@users.noreply.github.com>
This commit is contained in:
Oleksandr Klymenko
2025-07-11 22:42:45 +03:00
committed by GitHub
parent 048bba9499
commit 0a4f5542d9

View File

@@ -1,25 +1,46 @@
package com.thealgorithms.misc;
/**
* Utility class for operations to find the range of occurrences of a key
* in a sorted (non-decreasing) array, and to count elements less than or equal to a given key.
*/
public final class RangeInSortedArray {
private RangeInSortedArray() {
}
// Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums'
// Gives [-1, -1] in case element doesn't exist in array
/**
* Finds the first and last occurrence indices of the key in a sorted array.
*
* @param nums sorted array of integers (non-decreasing order)
* @param key the target value to search for
* @return int array of size two where
* - index 0 is the first occurrence of key,
* - index 1 is the last occurrence of key,
* or [-1, -1] if the key does not exist in the array.
*/
public static int[] sortedRange(int[] nums, int key) {
int[] range = new int[] {-1, -1};
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true);
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false);
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true); // find left boundary
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false); // find right boundary
return range;
}
// Recursive altered binary search which searches for leftmost as well as rightmost occurrence
// of 'key'
/**
* Recursive altered binary search to find either the leftmost or rightmost occurrence of a key.
*
* @param nums the sorted array
* @param key the target to find
* @param left current left bound in search
* @param right current right bound in search
* @param range array to update with boundaries: range[0] for leftmost, range[1] for rightmost
* @param goLeft if true, searches for leftmost occurrence; if false, for rightmost occurrence
*/
public static void alteredBinSearch(int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
if (left > right) {
return;
}
int mid = (left + right) >>> 1;
int mid = left + ((right - left) >>> 1);
if (nums[mid] > key) {
alteredBinSearch(nums, key, left, mid - 1, range, goLeft);
} else if (nums[mid] < key) {
@@ -41,11 +62,19 @@ public final class RangeInSortedArray {
}
}
// Iterative altered binary search which searches for leftmost as well as rightmost occurrence
// of 'key'
/**
* Iterative altered binary search to find either the leftmost or rightmost occurrence of a key.
*
* @param nums the sorted array
* @param key the target to find
* @param left initial left bound
* @param right initial right bound
* @param range array to update with boundaries: range[0] for leftmost, range[1] for rightmost
* @param goLeft if true, searches for leftmost occurrence; if false, for rightmost occurrence
*/
public static void alteredBinSearchIter(int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
while (left <= right) {
final int mid = (left + right) >>> 1;
int mid = left + ((right - left) >>> 1);
if (nums[mid] > key) {
right = mid - 1;
} else if (nums[mid] < key) {
@@ -55,33 +84,48 @@ public final class RangeInSortedArray {
if (mid == 0 || nums[mid - 1] != key) {
range[0] = mid;
return;
} else {
right = mid - 1;
}
right = mid - 1;
} else {
if (mid == nums.length - 1 || nums[mid + 1] != key) {
range[1] = mid;
return;
} else {
left = mid + 1;
}
left = mid + 1;
}
}
}
}
/**
* Counts the number of elements strictly less than the given key.
*
* @param nums sorted array
* @param key the key to compare
* @return the count of elements less than the key
*/
public static int getCountLessThan(int[] nums, int key) {
return getLessThan(nums, key, 0, nums.length - 1);
}
/**
* Helper method using binary search to count elements less than or equal to the key.
*
* @param nums sorted array
* @param key the key to compare
* @param left current left bound
* @param right current right bound
* @return count of elements less than or equal to the key
*/
public static int getLessThan(int[] nums, int key, int left, int right) {
int count = 0;
while (left <= right) {
final int mid = (left + right) >>> 1;
int mid = left + ((right - left) >>> 1);
if (nums[mid] > key) {
right = mid - 1;
} else if (nums[mid] <= key) {
count = mid + 1; // At least mid+1 elements exist which are <= key
} else {
// nums[mid] <= key
count = mid + 1; // all elements from 0 to mid inclusive are <= key
left = mid + 1;
}
}