@@ -10,52 +10,100 @@ Two versions of binary search has been implemented in this repository - BinarySe
1010Image Source: GeeksforGeeks
1111
1212BinarySearch is a more straightforward and intuitive version of the binary search algorithm. In this approach, after the
13- mid-value is calculated, the high and low pointers are adjusted by just one unit. From the above example, after mid
14- points to index 4 in the first search, the low pointer moves to index 5 (+1) when narrowing the search. Similarly, when
15- mid points to index 7 in the second search, the high pointer shifts to index 6 (-1) when narrowing the search. This
16- prevents any possibility of infinite loops.
13+ mid-value is calculated, the high or low pointer is adjusted by just one unit. From the above example, after mid points
14+ to index 4 in the first search, the low pointer moves to index 5 (+1 from 4) when narrowing the search. Similarly, when
15+ mid points to index 7 in the second search, the high pointer shifts to index 6 (-1 from 7) when narrowing the search.
16+ This prevents any possibility of infinite loops. During the search, the moment mid-value is equal to the target value,
17+ the search ends prematurely. Note that there is no need for a "condition" method as the condition is already captured
18+ in the predicates of the if-else blocks.
1719
1820## BinarySearchTemplated
1921
2022BinarySearchTemplated removes the condition that checks if the current mid-value is equal to the target (which helps to
2123end the search the moment the target is found). The template adds a "condition" method which will be modified based on
2224the requirements of the implementation.
2325
24- The narrowing of the search space differs from BinarySearch - only one of the high or low pointers will be adjusted by
25- one unit.
26+ The narrowing of the search space differs from BinarySearch - only the high pointer will be adjusted by one unit.
2627
2728This template will work for most binary search problems and will only require the following changes:
2829- Search space (high and low)
2930- Condition method
3031- Returned value (low or low - 1)
3132
3233### Search Space (Requires change)
33- Simply modify the initialisation of the high and low pointer according to the search space.
34+ Simply modify the initialisation of the high and low pointer according to the [ search space] ( #search-space-adjustment ) .
3435
3536### Condition (Requires change)
3637We assume that when the condition returns true, the current value "passes" and when the condition returns false, the
3738current value "fails".
3839
39- In this template, we want to find the first "pass" in the array.
40-
41- INSERT IMAGE OF FIRST PASS
40+ Note that in this template, the conditional blocks
41+ ```
42+ if (condition(x)) {
43+ high = mid;
44+ } else {
45+ low = mid + 1;
46+ }
47+ ```
48+ requires elements that "fail" the condition to be on the left of the elements that "pass" the condition, see below, in a
49+ sorted array due to the way the high and low pointers are reassigned.
50+
51+ ![ binary search templated 1 img] ( ../../../../../docs/assets/images/BinarySearchTemplated1.jpeg )
52+
53+ Hence, we will need to implement a condition method that is able to discern between arrays that "pass" and "fail"
54+ accurately and also place them in the correct relative positions i.e. "fail" on the left of "pass". Suppose we change
55+ the condition method implementation in BinarySearchTemplated from ` value >= target ` to ` value <= target ` , what will
56+ happen?
57+ <details >
58+ <summary > <b >what will happen?</b > </summary >
59+ The array becomes "P P F F F F" and the low and high pointers are now reassigned wrongly.
60+ </details >
4261
4362### Returned Value (Requires change)
44- In the implementation of BinarySearchTemplated, return low was used to find the first "pass".
63+ In this implementation of BinarySearchTemplated, we return the first "pass" in the array with ` return low ` . This is
64+ because our condition method implementation encompasses the target value that we are finding i.e. when
65+ ` value == target ` .
66+
67+ ``` java
68+ public static boolean condition(int value, int target) {
69+ return value >= target;
70+ }
71+ ```
72+ ![ binary search templated 1 img] ( ../../../../../docs/assets/images/BinarySearchTemplated2.jpeg )
73+
74+ However, if we want to return the last "fail" in the array, we will ` return low - 1 ` .
75+
76+ Suppose now we modify the condition to be ` value > target ` , how can we modify our BinarySearchTemplated to still work as
77+ expected?
78+ <details >
79+ <summary > <b >value > target?</b > </summary >
80+ Replace ` return low ` with ` return low - 1 ` and replace arr[ low] with arr[ low - 1] as now the target value is the last
81+ "fail".
82+ </details >
4583
46- EXPLANATION TBC, STILL THINKING HOW TO PHRASE IT.
4784
4885### Search Space Adjustment
49- What should be the search space adjustment? (Why only low = mid + 1)
86+ What should be the search space adjustment? Why is only low reassigned with an increment and not high?
87+
88+ Due to the nature of floor division in Java's \ operator, if there are two mid-values within the search range, which is
89+ when the number of elements is even, the first mid-value will be selected. Suppose we do not increment the low pointer
90+ during reassignment, ` low = mid ` , let us take a look at the following example:
91+
92+ ![ binary search templated 1 img] ( ../../../../../docs/assets/images/BinarySearchTemplated3.jpeg )
93+
94+ The search space has been narrowed down to the range of index 1 (low) to 2 (high). The mid-value is calculated,
95+ ` mid = (1 + 2) / 2 ` , to be 1 due to floor division. Since ` 2 < 5 ` , we enter the else block where there is reassignment
96+ of ` low = mid ` . This means that the low pointer is still pointing to index 1 and the high pointer remains unchanged at
97+ index 2. This results in an infinite loop as the search range is not narrowed down.
5098
51- Due to the nature of floor division in Java's \ operator, the searched mid-index will always be smaller than the high
52- pointer of the previous search range. On the other hand, low = mid + 1, ensures that the searched mid-index is always
53- larger than the low pointer of the previous search range. This ensures that the search range is narrowed in every loop
54- and prevents the possibility of infinite loops.
99+ To resolve this issue, we need ` low = mid + 1 ` , which will result in the low pointer pointing to index 2 in this
100+ scenario. We still ensure correctness because the mid-value is not the target value, as the mid-value < target, and we
101+ can safely exclude it from the search range.
55102
56- INSERT IMAGE HERE TO EXPLAIN
103+ Why do we not need to increment the high pointer during reassignment? This is because the mid-value could be the target
104+ as the condition implemented is ` value >= target ` , hence, we cannot exclude it from the search range.
57105
58- As we close in towards the target value, the final low = mid + 1 narrows the search range from low. TBC ON EXPLANATION
106+ See [ here ] ( ./binarySearchTemplatedExamples/README.md ) to use the template for other problems
59107
60108Credits: [ Powerful Ultimate Binary Search Template] ( https://leetcode.com/discuss/general-discussion/786126/python-powerful-ultimate-binary-search-template-solved-many-problems )
61109
0 commit comments