Bea.AI coding blog
  • Tree
    • Tree Traverse
    • Iteration based traverse
    • Typical problems and solutions
      • Max width of binary tree
      • Binary Tree & BST Serialize & Deserialize
      • Lowest common ancestor (LCA) for Binary Tree and BST
      • Subproblem-based Approach for Resolving Max Value on Trees
      • Path sum III
  • Graph
  • Data structure
    • Java data structure
  • Algorithm general templates
    • Tree
    • Trie
    • Graph
  • Java Algorithm Tips and Tricks
    • Java concurrent list
  • Coding patterns & Strategies
  • Coding patterns & template
    • 1. Binary Search
    • 2. Two Pointer
    • 3. Sliding Window
    • 4. Backtracking
    • 5. DFS
    • 6. BFS
    • 7. Stack
    • 8. Heap
    • 9. Prefix Sum
    • 10. Linked List
    • 11. BST
    • 12. Line sweep
    • 14. Tree
    • 15. Graph
    • 16. Bit manipulation
    • 17. Matrix
    • 18. Monotonic Stack
    • 19. Sorting
    • 20. Union Find
    • 21. Trie
    • 22. Dynamic programming
    • 23. Customized Data Structure
  • Code interview steps
  • Leetcode
    • Tree
      • Traversal
      • Construction and Conversion
      • Search and Validation
      • Manipulation and Modification
      • Special Trees
      • Miscellaneous
    • Dynamic programing
      • Classic DP Problems
      • Sequence/Array DP
      • Matrix DP
      • Knapsack Problems
      • String DP
      • Tree/Graph DP
      • Optimization Problems
      • Combinatorial DP
    • DFS
      • Graph Traversal
      • Path Finding
      • Tree Traversal
      • Backtracking
      • Topological Sorting
      • Traversal Order
      • Dynamic Programming with DFS
      • Connected Components
    • BFS
      • Graph
      • Tree
      • Matrix
      • String
      • Others
    • Two points
      • Array
      • String
      • Linked List
      • Sorting
      • Others
    • LinkedList
      • Basic Operations
      • Cycle Detection and Handling
      • Intersection and Union
      • Partitioning and Merging
      • Palindrome
      • Miscellaneous
    • Backtracking
    • Binary Search
    • Union Find
    • Trie
    • Sort
    • Heap
    • Randomness
    • Topological sort
    • Stack
    • HashTable
    • Sliding Window
  • Blind 75
    • Array
    • Binary
    • Dynamic Programming
    • Graph
    • Interval
    • LinkedList
    • Matrix
    • String
    • Tree
    • Heap
  • Companies
    • Apple
Powered by GitBook
On this page
  • Classic Binary Search:
  • 1. 704. Binary Search - A straightforward implementation of the binary search on an array.
  • Search in Rotated Sorted Array:
  • 2. 33. Search in Rotated Sorted Array - Find an element in an array that has been rotated.
  • Find the Smallest or Largest Index
  • 3. 278. First Bad Version - Find the first version where a product became bad.
  • 4. 35. Search Insert Position - Find the index to insert a target value in a sorted array.
  • Finding Boundaries:
  • 5. 34. Find First and Last Position of Element in Sorted Array - Find the first and last position of a given target.
  • Search in a 2D Matrix:
  • 6. 74. Search a 2D Matrix - Determine if a target value exists in a matrix that has both its rows and columns sorted.
  • Capacity To Ship Packages Within D Days:
  • 7. 1011. Capacity To Ship Packages Within D Days - Decide on the minimum capacity of a ship so that all the packages can be shipped within D days.
  • Minimize Maximum of Array
  • 8. 410. Split Array Largest Sum - Find the smallest largest sum after splitting the array into m parts.
  • K-th Element in Two Sorted Arrays
  • 9. 4. Median of Two Sorted Arrays - Find the median of two sorted arrays.
  • 10. 719. Find K-th Smallest Pair Distance - Find the k-th smallest distance among all the pairs.
  • Allocation Problems
  • 11. 875. Koko Eating Bananas - Find the minimum eating speed to eat all the bananas within H hours.
  • 12. 1231. Divide Chocolate - You have K friends and some pieces of chocolate and you want to maximize the minimum sweetness of the chocolate sections you will share with your friends.
  • 13. Binary Search Template III - General template for problems where you have to find a moment in time when an event occurs.
  1. Leetcode

Binary Search

Classic Binary Search:

1. 704. Binary Search - A straightforward implementation of the binary search on an array.

  1. Problem Description and Problem Link: Problem: "704. Binary Search" You are given a sorted array of integers nums and a target value. You need to implement the binary search algorithm to find the target value in the array.

Link to the problem on LeetCode: https://leetcode.com/problems/binary-search/

  1. Optimized Java Code using Binary Search:

public class BinarySearch {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        
        // Target not found
        return -1;
    }
}
  1. Detailed Algorithm and Thinking Process:

The binary search algorithm is a classic algorithm for searching for a target value in a sorted array. It works by repeatedly dividing the search space in half until the target value is found or the search space is empty.

Here's how the algorithm works:

  1. Initialize two pointers, left = 0 and right = nums.length - 1, which represent the search space.

  2. While the search space is not empty (left <= right), do the following: a. Find the middle element of the search space: mid = left + (right - left) / 2. b. If the middle element is equal to the target, return its index (mid). c. If the middle element is less than the target, update the left pointer to mid + 1 to search in the right half of the search space. d. If the middle element is greater than the target, update the right pointer to mid - 1 to search in the left half of the search space.

  3. If the target is not found after the while loop, return -1 to indicate that the target does not exist in the array.

During an interview, you can explain the binary search algorithm step by step and highlight its key features:

  • Efficiency: Binary search has a time complexity of O(log n) since it halves the search space in each iteration. This makes it very efficient for searching in large sorted arrays.

  • Requirement: The array must be sorted in ascending order for binary search to work correctly.

  • Division of Search Space: Binary search divides the search space in half at each step, narrowing down the range in which the target can be found. This approach eliminates the need to search every element in the array.

  • Optimization: By calculating the middle index as mid = left + (right - left) / 2, we prevent the overflow that can occur with mid = (left + right) / 2 when left and right are large numbers.

By following this approach and explaining the algorithm clearly to the interviewer, you can demonstrate your understanding of binary search and your ability to solve the given problem efficiently.

Search in Rotated Sorted Array:

2. 33. Search in Rotated Sorted Array - Find an element in an array that has been rotated.

  1. Problem Description:

The problem "33. Search in Rotated Sorted Array" on LeetCode asks us to find a target element in a rotated sorted array. The rotated sorted array is an array that has been rotated at some pivot index, which means some elements from the front of the array have been moved to the end of the array. We need to return the index of the target element in the array, or -1 if it does not exist.

Link to the problem: https://leetcode.com/problems/search-in-rotated-sorted-array/

  1. Optimized Java Code using Binary Search:

public class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] == target) {
                return mid;
            }
            
            // Check if the left half is sorted
            if (nums[left] <= nums[mid]) {
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } 
            // Check if the right half is sorted
            else {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        
        return -1;
    }
}
  1. Algorithm Explanation:

The idea behind this algorithm is to use binary search to divide the array into two halves and determine which half is sorted. We keep updating the left and right pointers based on whether the target element falls within the sorted half or the rotated half.

Here are the steps to think through this algorithm during an interview:

  1. Initialize the left and right pointers to the start and end indices of the array, respectively, as we want to search in the entire array.

  2. Start a loop and continue until the left pointer is less than or equal to the right pointer.

  3. Calculate the middle index by adding the left and right pointers and dividing by 2. This gives us the mid index between the left and right indices.

  4. Check if the element at the mid index is the target element. If it is, return the mid index as the result.

  5. Next, we need to determine which half of the array is sorted and which half is rotated.

  6. Check if the left half is sorted by comparing the element at the left index with the element at the mid index. If it is sorted and the target element falls within the range of the left half, update the right pointer to mid - 1. Otherwise, update the left pointer to mid + 1.

  7. If the left half is not sorted, then the right half must be sorted. Check if the target element falls within the range of the right half. If it does, update the left pointer to mid + 1. Otherwise, update the right pointer to mid - 1.

  8. Repeat steps 3-7 until the target element is found or the left pointer becomes greater than the right pointer.

  9. If the target element is not found, return -1.

By following this algorithm, we can efficiently find the target element in the rotated sorted array using binary search.

Find the Smallest or Largest Index

3. 278. First Bad Version - Find the first version where a product became bad.

  1. Problem Description (Leetcode link: https://leetcode.com/problems/first-bad-version/):

You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product is bad and has a bug. Each version is denoted by a positive integer. Versions are sequentially numbered from 1 to n. You need to find the first bad version where all following versions are also bad.

Given a function boolean isBadVersion(int version) which will return whether a version is bad or not, implement a solution to find the first bad version using the minimum number of calls to isBadVersion().

  1. Optimized Java code using binary search for the problem "278. First Bad Version":

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1;
        int right = n;

        while (left < right) {
            int mid = left + (right - left) / 2;

            if (isBadVersion(mid)) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        
        return left;
    }
}
  1. Algorithm Description and Interview Process:

The problem can be solved using the binary search algorithm, which allows us to quickly find the first bad version.

The binary search algorithm works by repeatedly dividing the search space in half until the target is found or the search space becomes empty.

Here's a step-by-step breakdown of the algorithm:

  1. Initialize two pointers, left and right, which represent the starting and ending points of the search space (1 to n).

  2. While left is less than right, calculate the middle position as (left + right) / 2.

  3. Check if the middle version is bad or not. If it is bad, it means that all following versions will also be bad. Update right to be the middle version.

  4. If the middle version is not bad, it means that all previous versions are not bad. Update left to be the next version after the middle.

  5. Repeat steps 2-4 until left is equal to right, at which point we have found the first bad version.

During the interview process, it is important to communicate the binary search algorithm and its steps clearly to the interviewer. Explain how the algorithm reduces the search space by half at each iteration, leading to an efficient solution. Additionally, make sure to mention and handle any edge cases, such as when the first version is bad or when the number of versions is very large.

4. 35. Search Insert Position - Find the index to insert a target value in a sorted array.

  1. Problem Description:

The problem "35. Search Insert Position" on LeetCode asks us to find the position (index) to insert a target value into a sorted array. If the target value is already present in the array, we need to return its index. If the target value is not present in the array, we need to return the index where it would be inserted in order to maintain sorted order.

LeetCode Problem Link: https://leetcode.com/problems/search-insert-position/

  1. Optimized Java Code using Binary Search:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 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 low;
    }
}
  1. Detailed Description and Algorithm:

The problem requires finding the index to insert a target value into a sorted array. Since the given array is sorted, we can use binary search to solve this problem efficiently.

The algorithm used in the code is as follows:

  • Initialize two pointers, low and high. low points to the start of the array and high points to the end of the array.

  • Run a while loop until low <= high, which means there are still elements to search over.

  • Inside the loop, calculate the middle index using mid = low + (high - low) / 2 to avoid integer overflow.

  • Check if the element at the middle index, nums[mid], is equal to the target value. If so, return the middle index as it matches the target element.

  • If nums[mid] < target, it means the target value could be present in the right half of the array. So, update low = mid + 1 to search in the right half.

  • If nums[mid] > target, it means the target value could be present in the left half of the array. So, update high = mid - 1 to search in the left half.

  • If the loop exits without finding the target value, it means the target value is not present in the array. At this point, low would be pointing to the right position to insert the target value while maintaining the sorted order. So, return low as the answer.

During the interview process, it's important to understand the problem requirements and constraints well before proceeding to solve it. The problem of finding the index to insert a target value in a sorted array can be efficiently solved using binary search, as demonstrated in the code. Analyze the time complexity of the algorithm to ensure its efficiency.

Finding Boundaries:

5. 34. Find First and Last Position of Element in Sorted Array - Find the first and last position of a given target.

  1. Problem Description: The problem is to find the first and last position of a given target value in a sorted array of integers. If the target is not found, the function should return [-1, -1]. The problem can be found on LeetCode here: https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/

  2. Optimized Java Code using Binary Search: Below is the optimized Java code using binary search to find the first and last position of a target value in the sorted array:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] result = new int[2];
        result[0] = findFirstPosition(nums, target); // Find first position
        result[1] = findLastPosition(nums, target); // Find last position
        return result;
    }
    
    private int findFirstPosition(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int firstPosition = -1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] >= target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
            
            if (nums[mid] == target) {
                firstPosition = mid;
            }
        }
        
        return firstPosition;
    }
    
    private int findLastPosition(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int lastPosition = -1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] <= target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
            
            if (nums[mid] == target) {
                lastPosition = mid;
            }
        }
        
        return lastPosition;
    }
}
  1. Algorithm Explanation and Interview Process Thoughts: The binary search algorithm is utilized here to find the first and last position of the target value in the sorted array.

The searchRange function initializes an array result of size 2 to store the first and last positions. It then calls two helper functions: findFirstPosition and findLastPosition.

In both helper functions, a standard binary search approach is used with slight modifications. For findFirstPosition, the mid element is checked if it is greater than or equal to the target. If it is, the right pointer is updated to mid - 1. If it isn't, the left pointer is updated to mid + 1. Additionally, if the mid element is equal to the target, the variable firstPosition is updated with the mid index.

Similarly, for findLastPosition, the mid element is checked if it is less than or equal to the target. If it is, the left pointer is updated to mid + 1. If it isn't, the right pointer is updated to mid - 1. If the mid element is equal to the target, the variable lastPosition is updated with the mid index.

Both helper functions return the first and last positions respectively.

During an interview, it's important to understand the problem requirements and constraints. Then, explain the binary search approach in detail, including how the pointers and mid elements are updated. Emphasize the importance of updating the position variables when the target is found.

Make sure to discuss different edge cases such as when the target value is not present in the array, or when the array is empty. Additionally, discuss the time complexity of the solution, which is O(log n) as it utilizes binary search.

Search in a 2D Matrix:

6. 74. Search a 2D Matrix - Determine if a target value exists in a matrix that has both its rows and columns sorted.

  1. Problem Description: The problem "74. Search a 2D Matrix" on LeetCode: https://leetcode.com/problems/search-a-2d-matrix/

Given a matrix that is sorted both horizontally and vertically, we need to determine if a target value exists in the matrix. The matrix has the following properties:

  • The integers in each row are sorted in ascending order from left to right.

  • The integers in each column are sorted in ascending order from top to bottom.

  1. Optimized Java Code using Binary Search:

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        
        int rows = matrix.length;
        int cols = matrix[0].length;
        
        int start = 0;
        int end = rows * cols - 1;
        
        while (start <= end) {
            int mid = start + (end - start) / 2;
            int midValue = matrix[mid / cols][mid % cols];
            
            if (midValue == target) {
                return true;
            } else if (midValue < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        
        return false;
    }
}
  1. Detailed Description of the Algorithm:

The problem can be solved using a binary search approach.

We begin by initializing the start and end indices to the first and last cell of the matrix, respectively. Then, we enter a while loop with the condition start <= end.

Inside the loop, we calculate the middle index of the matrix using the formula mid = start + (end - start) / 2. We obtain the corresponding value midValue in the matrix by calculating matrix[mid / cols][mid % cols].

We compare midValue with the target value. If they are equal, we return true as the target value exists in the matrix. If midValue is less than the target, we update start to mid + 1 to search in the right half of the remaining sub-array. If midValue is greater than the target, we update end to mid - 1 to search in the left half of the remaining sub-array.

If the while loop terminates without finding the target value, we return false as it does not exist in the matrix.

During an interview, it is important to communicate the following points while thinking through the problem:

  • The matrix is sorted both horizontally and vertically, which suggests that we can apply binary search.

  • Instead of treating the 2D matrix as a 2D structure, we can think of it as a 1D array by mapping the indices.

  • By choosing the middle index correctly and updating the start and end indices based on the comparison with the target value, we can reduce the search space in each iteration.

  • The time complexity of this approach is O(log(N)), where N = number of elements in the matrix. This is because we eliminate half of the search space in each iteration of the binary search.

By explaining and implementing this approach, you can demonstrate your understanding of binary search and problem-solving skills during an interview.

Capacity To Ship Packages Within D Days:

7. 1011. Capacity To Ship Packages Within D Days - Decide on the minimum capacity of a ship so that all the packages can be shipped within D days.

  1. The problem "1011. Capacity To Ship Packages Within D Days" on LeetCode can be found at the following link:

  2. Here is the optimized Java code that solves the problem using binary search:

class Solution {
    public int shipWithinDays(int[] weights, int D) {
        int left = 0; // minimum capacity of the ship
        int right = 0; // maximum capacity of the ship
        
        for (int weight : weights) {
            left = Math.max(left, weight); // minimum capacity should be at least the maximum weight
            right += weight; // maximum capacity should be the sum of all weights
        }
        
        while (left < right) {
            int mid = left + (right - left) / 2; // choose the middle value as the current capacity
            
            int days = 1; // keep track of days needed to ship all packages
            int currentWeight = 0; // current package's weight being processed
            
            for (int weight : weights) {
                if (currentWeight + weight > mid) {
                    days += 1; // need to ship on the next day due to exceeding capacity
                    currentWeight = 0; // reset current package's weight
                }
                currentWeight += weight; // add package's weight to the current weight
            }
            
            if (days > D) {
                left = mid + 1; // increase capacity if it takes more days than allowed
            } else {
                right = mid; // decrease capacity if it takes fewer days or exactly D days
            }
        }
        
        return left; // minimum capacity found
    }
}
  1. Algorithm description and thinking process during an interview:

    • The problem asks us to find the minimum capacity of a ship so that all the packages can be shipped within D days.

    • We need to minimize the capacity of the ship, so it's a perfect problem for binary search.

    • First, we need to determine the range for the binary search. The minimum capacity should be at least the maximum weight of the packages, and the maximum capacity should be the sum of all weights.

    • Next, we start the binary search. In each iteration, we choose the middle value as the current capacity and simulate the shipping process.

    • We keep track of the number of days needed to ship all packages. If the current capacity is not enough to ship a package, we increase the number of days and reset the current package's weight.

    • If the number of days required is more than D, it means the capacity is too low. So, we increase the left boundary by setting left = mid + 1.

    • If the number of days required is equal to or less than D, it means the capacity is sufficient. We decrease the right boundary by setting right = mid.

    • When left == right, we have found the minimum capacity, and we can return it.

    • The time complexity of this approach is O(n * log(sum of weights)), where n is the number of packages.

    • It's important to explain the binary search approach and why it is more efficient than a brute-force approach that checks all possible capacities.

    • Additionally, discussing the initial range selection and the iterative process of binary search will demonstrate both understanding and coding skills.

Minimize Maximum of Array

8. 410. Split Array Largest Sum - Find the smallest largest sum after splitting the array into m parts.

  1. Optimized Java Code: Here is the optimized Java code, using binary search, to solve the "410. Split Array Largest Sum" problem:

class Solution {
    public int splitArray(int[] nums, int m) {
        long left = 0;
        long right = 0;
        
        // Initialize left and right pointers
        for (int num : nums) {
            left = Math.max(left, num);
            right += num;
        }
        
        // Perform binary search
        while (left < right) {
            long mid = left + (right - left) / 2;
            int partitions = countPartitions(nums, mid);
            
            if (partitions > m) {
                // If the number of partitions is more than m, increase the sum
                left = mid + 1;
            } else {
                // If the number of partitions is less than or equal to m, decrease the sum
                right = mid;
            }
        }
        
        return (int) left;
    }
    
    private int countPartitions(int[] nums, long sum) {
        int count = 1;
        long currSum = 0;
        
        for (int num : nums) {
            if (currSum + num > sum) {
                // If adding the current number exceeds the sum, start a new partition
                currSum = num;
                count++;
            } else {
                // Otherwise, add the number to the current partition
                currSum += num;
            }
        }
        
        return count;
    }
}
  1. Algorithm and Interview Insights: The problem can be solved using a binary search approach. The basic idea is to find the range of possible largest sums and perform a binary search within that range to find the smallest largest sum.

During an interview, you can approach this problem as follows:

  • Understand the problem statement and constraints.

  • Observe that the smallest largest sum will lie in the range of maximum element to the sum of all elements in the array. So, initialize left and right pointers accordingly.

  • Perform a binary search until the left pointer is less than the right pointer.

  • In each iteration, calculate the middle value and count the number of partitions with sums less than or equal to the middle value.

  • If the count is greater than m, it means we need to increase the sum, so update the left pointer.

  • If the count is less than or equal to m, it means we can decrease the sum, so update the right pointer.

  • Finally, return the left pointer as the result, which will be the smallest largest sum.

By following this algorithm and understanding its pseudocode, you can efficiently solve the problem during an interview. Remember to explain your approach, write clean code, and test it with different test cases to ensure its correctness.

K-th Element in Two Sorted Arrays

9. 4. Median of Two Sorted Arrays - Find the median of two sorted arrays.

  1. Problem Description and LeetCode Link: The problem "4. Median of Two Sorted Arrays" asks us to find the median of two sorted arrays. Given two sorted arrays, nums1 and nums2, of sizes m and n respectively, we need to find the median of the two arrays.

LeetCode Link: https://leetcode.com/problems/median-of-two-sorted-arrays/

  1. Optimized Java Code using Binary Search:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        // Ensure that nums1 is always the smaller array
        if (nums1.length > nums2.length) {
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
        }
        
        int m = nums1.length;
        int n = nums2.length;
        int left = 0, right = m;
        int median1 = 0, median2 = 0;
        
        // Start the binary search on the smaller array nums1
        while (left <= right) {
            int partition1 = (left + right) / 2;
            int partition2 = (m + n + 1) / 2 - partition1;
            
            int maxLeft1 = (partition1 == 0) ? Integer.MIN_VALUE : nums1[partition1 - 1];
            int minRight1 = (partition1 == m) ? Integer.MAX_VALUE : nums1[partition1];
            
            int maxLeft2 = (partition2 == 0) ? Integer.MIN_VALUE : nums2[partition2 - 1];
            int minRight2 = (partition2 == n) ? Integer.MAX_VALUE : nums2[partition2];
            
            if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {
                // Found the correct partitions
                
                // Check if the total number of elements is odd or even
                if ((m + n) % 2 == 0) {
                    median1 = Math.max(maxLeft1, maxLeft2);
                    median2 = Math.min(minRight1, minRight2);
                    return (median1 + median2) / 2.0;
                } else {
                    median1 = Math.max(maxLeft1, maxLeft2);
                    return median1;
                }
            } else if (maxLeft1 > minRight2) {
                // Need to move left in partition1
                right = partition1 - 1;
            } else {
                // Need to move right in partition1
                left = partition1 + 1;
            }
        }
        
        // Should never reach this point if input is correct
        return -1;
    }
}
  1. Detailed Description of the Algorithm and Interview Thought Process:

  • In this problem, we are given two sorted arrays and asked to find the median of the combined array.

  • To solve this problem efficiently, we can use the binary search algorithm. We perform a binary search on the smaller array, which helps us divide both arrays into two parts such that the left partitions have smaller elements and the right partitions have larger elements.

  • The idea is to find the correct partitions in both arrays such that:

    • All elements in the left partitions are smaller than or equal to all elements in the right partitions.

    • The total number of elements in the left partitions is equal to the total number of elements in the right partitions (or one element more in case of an odd total number of elements).

  • We find the correct partitions by maintaining two pointers, partition1 and partition2, which divide both arrays. We adjust these pointers based on the comparison of elements in the partitions until we find the correct partitions.

  • Once we find the correct partitions, we can calculate the median based on the number of elements and whether the total number is odd or even.

  • During an interview, it is important to discuss and clarify any doubts regarding the problem, understand the expected input and output formats, and consider possible edge cases (such as empty arrays or arrays of different sizes). It is also crucial to clearly explain the algorithm and its time complexity. Practice writing the code and running through some sample test cases to ensure correctness.

10. 719. Find K-th Smallest Pair Distance - Find the k-th smallest distance among all the pairs.

  1. Problem Description:

The problem is to find the k-th smallest distance among all pairs given an array of integers. The distance between two integers is defined as the absolute difference between them.

Link to the problem on LeetCode: https://leetcode.com/problems/find-k-th-smallest-pair-distance/

  1. Optimized Java Code using Binary Search:

import java.util.Arrays;

class Solution {
    public int smallestDistancePair(int[] nums, int k) {
        Arrays.sort(nums); // sorting the input array
        
        int n = nums.length;
        int left = 0; // minimum possible distance
        int right = nums[n - 1] - nums[0]; // maximum possible distance
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            int count = 0;
            int start = 0; // pointer to leftmost element
            
            // Counting the number of pairs with distance <= mid
            for (int i = 0; i < n; i++) {
                while (nums[i] - nums[start] > mid) {
                    start++;
                }
                count += i - start;
            }
            
            // Based on count, adjust the range for binary search
            if (count >= k) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        
        return left;
    }
}
  1. Detailed Explanation:

The algorithm to solve this problem is based on binary search. We first sort the input array to make it easier to find the distances.

The idea is to perform a binary search on the range of possible distances. We start with the minimum possible distance (0) and the maximum possible distance (difference between the largest and smallest element).

In each iteration of the binary search, we calculate the mid distance and count the number of pairs with distance less than or equal to the mid. We use two pointers, i and start, to calculate this count efficiently.

The count variable keeps track of the number of pairs found so far. When the count is greater than or equal to k, it means we have found at least k pairs with distance less than or equal to the mid. In this case, we update the right pointer to the mid, reducing the range for the next binary search iteration.

If the count is less than k, it means we have found less than k pairs with distance less than or equal to the mid. In this case, we update the left pointer to mid + 1, increasing the range for the next binary search iteration.

Finally, when the left pointer crosses the right pointer, we have found the k-th smallest pair distance. We return the value of the left pointer as the answer.

During the interview process, it's important to explain the thought process and the steps involved in solving this problem efficiently. Emphasize the use of binary search to narrow down the range of possible distances and point out the need for sorting the array to simplify the calculations. Also, make sure to clarify any queries the interviewers may have regarding the problem statement or the implementation details.

Allocation Problems

11. 875. Koko Eating Bananas - Find the minimum eating speed to eat all the bananas within H hours.

  1. The problem "875. Koko Eating Bananas" on LeetCode can be found at the following link: https://leetcode.com/problems/koko-eating-bananas/

The problem statement is as follows: There are N piles of bananas, where the ith pile has piles[i] bananas. Koko loves to eat bananas. However, she can only eat at a certain speed. She eats K bananas per hour.

Given piles[] representing the number of bananas in each pile, and H representing the total number of hours Koko wants to spend eating, we need to find the minimum integer value of K such that she can eat all the bananas within H hours.

  1. Below is the optimized Java code using binary search for solving the problem "875. Koko Eating Bananas":

class Solution {
    public int minEatingSpeed(int[] piles, int H) {
        int left = 1; // minimum possible eating speed (at least 1 banana per hour)
        int right = getMaxPile(piles); // maximum possible eating speed (maximum bananas in any pile)
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            
            if (canEatAll(piles, H, mid)) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        
        return left;
    }
    
    private boolean canEatAll(int[] piles, int H, int speed) {
        int hoursRequired = 0;
        
        for (int pile : piles) {
            hoursRequired += (pile + speed - 1) / speed; // ceil(pile / speed)
        }
        
        return hoursRequired <= H;
    }
    
    private int getMaxPile(int[] piles) {
        int maxPile = Integer.MIN_VALUE;
        
        for (int pile : piles) {
            maxPile = Math.max(maxPile, pile);
        }
        
        return maxPile;
    }
}
  1. Algorithm and Approach:

  • To solve this problem, we can use a binary search approach.

  • The binary search will be performed on the range of possible eating speeds (from the minimum possible eating speed to the maximum possible eating speed).

  • We initially set the left pointer to 1 (minimum possible speed) and the right pointer to the maximum pile size (maximum possible speed). We will find the midpoint (mid) of these two pointers.

  • We check whether it is possible to eat all the bananas within H hours with the current mid speed by using the canEatAll() function. If it is possible, we update the right pointer to mid, indicating that we can further minimize the eating speed. If not, we update the left pointer to mid+1, indicating that we need a higher eating speed.

  • We continue this binary search process until the left pointer becomes equal to the right pointer. At this point, we have found the minimum eating speed required to eat all the bananas within H hours.

  • We define the canEatAll() function to calculate the total hours required to eat all the bananas at a given speed. We iterate over the piles array and calculate the number of hours required for each pile (using ceil(piles[i] / speed)) and sum these hours. We return true if the total hours required is less than or equal to H, indicating it is possible to eat all the bananas in H hours with the current speed.

  • Finally, we define the getMaxPile() function to find the maximum pile size in the input piles array.

During an interview process, it is important to explain the problem first and clarify any ambiguities. Then, you can discuss possible approaches and their time complexity. Binary search is a very efficient approach for this problem, with a time complexity of O(log(max_pile * n)) where max_pile is the maximum pile size and n is the number of piles. You can demonstrate problem-solving skills by implementing the binary search algorithm and explaining the reasoning behind it.

12. 1231. Divide Chocolate - You have K friends and some pieces of chocolate and you want to maximize the minimum sweetness of the chocolate sections you will share with your friends.

  1. Problem Description: The problem "1231. Divide Chocolate" on LeetCode can be found at the following link: https://leetcode.com/problems/divide-chocolate/

Given an array of integers representing the sweetness level of each piece of chocolate, we need to divide the chocolate into K non-empty sections such that we maximize the minimum sweetness of any section. The goal is to find the maximum value of the minimum sweetness.

  1. Optimized Java Code using Binary Search:

class Solution {
    public int maximizeSweetness(int[] sweetness, int K) {
        int totalSweetness = 0;
        int maxSweetness = 0;
        
        for (int s : sweetness) {
            totalSweetness += s;
            maxSweetness = Math.max(maxSweetness, s);
        }
        
        int left = maxSweetness;
        int right = totalSweetness;
        
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            
            if (canDivide(sweetness, K + 1, mid)) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        
        return left;
    }
    
    private boolean canDivide(int[] sweetness, int numSections, int minSweetness) {
        int currentSum = 0;
        int sections = 0;
        
        for (int s : sweetness) {
            currentSum += s;
            
            if (currentSum >= minSweetness) {
                sections++;
                currentSum = 0;
            }
        }
        
        return sections >= numSections;
    }
}
  1. Algorithm and Approach: The problem asks us to divide the given chocolate into K non-empty sections such that we maximize the minimum sweetness of any section. To solve this problem, we can use binary search on the possible range of sweetness values.

First, we calculate the total sweetness of all the chocolate pieces and find the maximum sweetness value. These will serve as the initial boundaries for our binary search.

In each iteration of the binary search, we calculate the mid value using left + (right - left + 1) / 2 to ensure the correct rounding. Then, we check if we can divide the chocolate into K + 1 sections with a minimum sweetness of mid using the canDivide() helper method.

The canDivide() method simulates the division process and counts the number of sections that can be formed. If the number of sections is greater than or equal to K + 1, we update the left boundary to mid, otherwise, we update the right boundary to mid - 1.

We continue the binary search until the left and right boundaries converge (left >= right). At this point, the left value represents the maximum value of the minimum sweetness.

This approach utilizes binary search to efficiently find the optimal solution, reducing the time complexity to O(n * log(maxSweetness - minSweetness)). During an interview process, it's important to explain the binary search approach clearly and mention the time complexity analysis. Additionally, you can emphasize the importance of understanding the problem, breaking it down into subproblems, and implementing a well-structured solution.

13. Binary Search Template III - General template for problems where you have to find a moment in time when an event occurs.

  1. The problem I will explain is the "Binary Search Template III - General template for problems where you have to find a moment in time when an event occurs." The problem link to leetcode is: https://leetcode.com/discuss/general-discussion/786126/Binary-Search-Template-III-General-template-for-problems-where-you-have-to-find-a-moment-in-time-when-an-event-occurs.

  2. Here is the optimized Java code using binary search for the given problem:

public int findEventMoment(int target, int[] nums) {
    int left = 0;
    int right = nums.length - 1;
    
    while (left < right) {
        int mid = left + (right - left) / 2;
        
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    
    if (nums[left] != target) {
        return -1; // Moment not found
    }
    
    return left; // Moment found at index left
}
  1. Algorithm and Thought Process:

    • This problem is a typical binary search problem where we have to find a specific moment in time when an event occurs.

    • The given array num represents the time at which certain events occur.

    • We need to find the moment (index) in the array when the event occurred for the first time.

    • To solve this problem, we can use the Binary Search Template III.

    • Initially, we set the left pointer to the start of the array and the right pointer to the end of the array.

    • We then enter a loop where the condition is left < right.

    • In each iteration, we calculate the middle index using the formula mid = left + (right - left) / 2.

    • If the value at the middle index nums[mid] is less than the target, we update the left pointer to mid + 1, indicating that the event has not occurred yet and we need to search in the right half.

    • If the value at the middle index nums[mid] is greater than or equal to the target, we update the right pointer to mid, indicating that the event has occurred and we need to search in the left half.

    • We repeat this process until left becomes equal to right, meaning we have found the moment when the event occurred.

    • Finally, we check if the value at the found moment index nums[left] is equal to the target. If not, we return -1 indicating the event did not occur.

    • If the value at the found moment index nums[left] is equal to the target, we return left as the moment when the event occurred.

    This algorithm has a time complexity of O(log n) and is an efficient way to find the moment in time when an event occurs using binary search.

PreviousBacktrackingNextUnion Find

Last updated 1 year ago

Problem Description and LeetCode Link: The problem "410. Split Array Largest Sum" asks us to divide an array into m non-empty subarrays. We need to find the smallest largest sum among all the subarrays. The input consists of an array of positive integers nums and an integer m, where 1 ≤ nums.length ≤ 1000 and 1 ≤ m ≤ min(50, nums.length). You can find the problem on LeetCode using the following link:

LeetCode 1011. Capacity To Ship Packages Within D Days
410. Split Array Largest Sum