11package 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+ */
37public 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 }
0 commit comments