Solving Binary Search
To see the question, click here.
Naive Approach
The idea is to search the entire array to find the target. So, if the target is found, return the index; otherwise, return -1.
// TC: O(n)
// SC: O(1)
public class BinarySearch {
public int search(int[] nums, int target) {
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == target) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
BinarySearch bs = new BinarySearch();
int[] nums = { -1, 0, 3, 5, 9, 12 };
int target = 9;
System.out.println(bs.search(nums, target));
}
}
Performance
The time complexity of the search
method is O(n) because it iterates through the entire array to find the target element. The space complexity is O(1) because the algorithm uses constant extra space regardless of the input size.
Refined Approach
Since the problem suggests using an algorithm with O(logn) runtime complexity, we will use Binary Search. The idea is to create a function called binarySearch
which recursively halves the search range based on the element at the mid
position.
// TC: O(logn)
// SC: O(logn)
public class BinarySearch {
public int binarySearch(int low, int high, int[] nums, int target) {
if (low > high)
return -1;
int mid = low + (high - low) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
return binarySearch(mid + 1, high, nums, target);
return binarySearch(low, mid - 1, nums, target);
}
public int search(int[] nums, int target) {
int n = nums.length;
return binarySearch(0, n - 1, nums, target);
}
public static void main(String[] args) {
BinarySearch bs = new BinarySearch();
int[] nums = { -1, 0, 3, 5, 9, 12 };
int target = 9;
System.out.println(bs.search(nums, target));
}
}
Performance
The time complexity of the binarySearch
method is O(log n). This is because the algorithm divides the search space in half at each step, leading to a logarithmic time complexity. The space complexity is O(log n) as well. This is because the algorithm uses recursion to perform the search, and the maximum depth of the recursion tree is log n.
Efficient Approach
Instead of doing recursive calls, we can maintain three pointers low
, mid
, and high
to effectively search the target. If the target is present at mid
then we return the mid
. If the target is less than the element present at mid
, then it may be possible that the number lies in between low
and mid
. We will then move high
to mid - 1
. Similarly, if the target is greater than the element present at mid
, then it may be possible that the number lies in between mid
and high
. We will then move low
to mid + 1
. This is the key step as the array is sorted. We will continue doing this until low
crosses high
. If the target is not found, we will return -1.
// TC: O(logn)
// SC: O(1)
public class BinarySearch {
public int search(int[] nums, int target) {
int n = nums.length;
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
public static void main(String[] args) {
BinarySearch bs = new BinarySearch();
int[] nums = { -1, 0, 3, 5, 9, 12 };
int target = 9;
System.out.println(bs.search(nums, target));
}
}
Performance
The time complexity of the search
method is O(logn) because, at each step, the search space is divided in half. The space complexity is O(1) because the algorithm only uses constant extra space regardless of the input size.
Thank you for reading!
Check out other DSA patterns here.
You can support me by buying me a book.