Given a sorted list of integers of length N, determine if an element x is in the list without performing any multiplication, division, or bit-shift operations.
Since we cannot use multiplication, division, or bit-shift operations to calculate the middle index, we need an alternative approach. We can calculate the middle point using only addition and subtraction. The key insight is that mid = left + (right - left) / 2 can be rewritten using repeated addition to avoid division.
⏰ Time complexity: O(log N * log N), where the first log N comes from binary search iterations and the second log N comes from the repeated subtraction to calculate mid
🧺 Space complexity: O(1), using only constant extra space
We can optimize the mid calculation by using a more efficient approach. Instead of repeatedly subtracting 2, we can use the mathematical property that (a + b) / 2 = (a + b - (a + b) % 2) / 2. We can calculate (a + b) % 2 without division by checking if the sum is odd or even.
classSolution {
public:bool search(vector<int>& arr, int x) {
int left =0, right = arr.size() -1;
while (left <= right) {
int mid = left + findHalf(right - left);
if (arr[mid] == x) {
return true;
} elseif (arr[mid] < x) {
left = mid +1;
} else {
right = mid -1;
}
}
return false;
}
private:int findHalf(int n) {
if (n ==0) return0;
int result =0;
int doubled =0;
// Find largest number such that 2 * result <= n
while (doubled + doubled <= n) {
doubled++;
result++;
}
return result -1;
}
};
classSolution {
publicbooleansearch(int[] arr, int x) {
int left = 0, right = arr.length- 1;
while (left <= right) {
int mid = left + findHalf(right - left);
if (arr[mid]== x) {
returntrue;
} elseif (arr[mid]< x) {
left = mid + 1;
} else {
right = mid - 1;
}
}
returnfalse;
}
privateintfindHalf(int n) {
if (n == 0) return 0;
int result = 0;
int doubled = 0;
// Find largest number such that 2 * result <= nwhile (doubled + doubled <= n) {
doubled++;
result++;
}
return result - 1;
}
}
classSolution:
defsearch_optimized(self, arr: List[int], x: int) -> bool:
left, right =0, len(arr) -1while left <= right:
mid = left + self._find_half(right - left)
if arr[mid] == x:
returnTrueelif arr[mid] < x:
left = mid +1else:
right = mid -1returnFalsedef_find_half(self, n: int) -> int:
if n ==0:
return0 result =0 doubled =0# Find largest number such that 2 * result <= nwhile doubled + doubled <= n:
doubled +=1 result +=1return result -1
We can implement binary search recursively while maintaining the constraint of not using multiplication, division, or bit operations. This approach uses the same mid calculation technique but with a recursive structure that might be more intuitive for some scenarios.