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.