0% found this document useful (0 votes)
3 views

binarysearch_dsa

The document outlines several LeetCode problems involving binary search techniques on various data structures, including finding peak elements, searching in rotated sorted arrays, and searching in 2D matrices. Each problem specifies the requirements for time complexity, typically O(log n), and provides example inputs and outputs. Solutions are presented with Java code implementations and explanations of the underlying algorithms.

Uploaded by

Kaushal Bhatt
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

binarysearch_dsa

The document outlines several LeetCode problems involving binary search techniques on various data structures, including finding peak elements, searching in rotated sorted arrays, and searching in 2D matrices. Each problem specifies the requirements for time complexity, typically O(log n), and provides example inputs and outputs. Solutions are presented with Java code implementations and explanations of the underlying algorithms.

Uploaded by

Kaushal Bhatt
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 16

url:https://leetcode.

com/problems/find-peak-element/description/
problem:
A peak element is an element that is strictly greater than its neighbors.

Given a 0-indexed integer array nums, find a peak element, and return its index. If
the array contains multiple peaks, return the index to any of the peaks.

You may imagine that nums[-1] = nums[n] = -∞. In other words, an element is always
considered to be strictly greater than a neighbor that is outside the array.

You must write an algorithm that runs in O(log n) time.

Example 1:

Input: nums = [1,2,3,1]


Output: 2
Explanation: 3 is a peak element and your function should return the index number
2.
Example 2:

Input: nums = [1,2,1,3,5,6,4]


Output: 5
Explanation: Your function can return either index number 1 where the peak element
is 2, or index number 5 where the peak element is 6.

Constraints:

1 <= nums.length <= 1000


-231 <= nums[i] <= 231 - 1
nums[i] != nums[i + 1] for all valid i.

solution:
Approach: Modified Binary Search

The key insight is that if the middle element of the array is in a descending slope
(middle element is smaller than its left neighbor), then there must be a peak
element to its left. Similarly, if the middle element is in an ascending slope, a
peak exists to its right.
class Solution {
public int findPeakElement(int[] nums) {
int low = 0;
int high = nums.length - 1;

while (low < high) {


int mid = low + (high - low) / 2;

// Descending slope (peak lies on the left side)


if (nums[mid] < nums[mid + 1]) {
low = mid + 1;

// Ascending slope (peak lies on the right side)


} else {
high = mid;
}
}
return low; // Or return high (both point to a peak at the end)
}
}

Explanation:

Initialization: low starts at 0 and high at the end of the array.

Binary Search: In each iteration:

Calculate mid.
Case 1 (Descending Slope): If nums[mid] < nums[mid + 1], the peak must be on the
right side due to the array's properties. Update low to mid + 1.
Case 2 (Ascending Slope): The peak must be on the left side (or even at mid).
Update high to mid.
Termination: The loop continues until low and high converge on a peak element.
Returning either low or high is valid.

Key Points:

O(log n) Time Complexity: Binary search gives us logarithmic time complexity.


Handling Edge Cases: The imaginary -∞ values at the edges ensure that even the
first and last elements can be peaks without additional checks.

######################################################################

url : https://leetcode.com/problems/search-in-rotated-sorted-array/

problem:
There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is possibly rotated at an unknown


pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k],
nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For
example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become
[4,5,6,7,0,1,2].

Given the array nums after the possible rotation and an integer target, return the
index of target if it is in nums, or -1 if it is not in nums.

You must write an algorithm with O(log n) runtime complexity.

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0


Output: 4
Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3


Output: -1
Example 3:

Input: nums = [1], target = 0


Output: -1
Constraints:

1 <= nums.length <= 5000


-104 <= nums[i] <= 104
All values of nums are unique.
nums is an ascending array that is possibly rotated.
-104 <= target <= 104

solution:
Approach: Binary Search with Pivot Handling

Find the Pivot (Rotation Point): The rotated array essentially consists of two
sorted subarrays. First, find the index where the rotation occurs (the pivot).

Determine Target Subarray: Once you know the pivot, you can determine in which
sorted subarray the target might exist.

Standard Binary Search: Perform a standard binary search within the appropriate
subarray.

Code Implementation:

Java

Explain
class Solution {
public int search(int[] nums, int target) {
int low = 0;
int high = nums.length - 1;

// Find the pivot point


while (low < high) {
int mid = low + (high - low) / 2;
if (nums[mid] > nums[high]) {
low = mid + 1;
} else {
high = mid;
}
}

int pivot = low; // 'low' and 'high' converge to the pivot

// Reset boundaries for binary search based on the target


if (target >= nums[pivot] && target <= nums[nums.length - 1]) {
low = pivot;
high = nums.length - 1;
} else {
low = 0;
high = pivot - 1;
}

// Standard binary search


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; // Target not found


}
}
Use code with caution.
Explanation:

Finding the Pivot: The loop locates the point where the ascending order "breaks" –
this is the point of rotation.
Choosing the Subarray: The if condition after finding the pivot determines which
sorted subarray to search based on the target's potential location.
Standard Binary Search: A regular binary search is performed within the selected
subarray.
Key Points:

Logarithmic Time: The combination of two binary search steps gives us O(log n) time
complexity.
Adaptation: This is a clever adaptation of binary search to a modified sorting
scenario.

########################################################

url: https://leetcode.com/problems/search-a-2d-matrix
problem:
You are given an m x n integer matrix matrix with the following two properties:

Each row is sorted in non-decreasing order.


The first integer of each row is greater than the last integer of the previous row.
Given an integer target, return true if target is in matrix or false otherwise.

You must write a solution in O(log(m * n)) time complexity.

Example 1:

Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3


Output: true
Example 2:

Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13


Output: false

Constraints:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104

solution:
Approach: Binary Search with Smart Indexing

The insight is to treat the entire matrix as a single sorted array but access its
elements using row and column calculations. Since each row is sorted, and the first
element of each row is larger than the previous row's last element, we can
effectively perform a binary search over the entire matrix space.

Code Implementation:

Java

Explain
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;

int low = 0;
int high = m * n - 1;

while (low <= high) {


int mid = low + (high - low) / 2;
int midElement = matrix[mid / n][mid % n]; // Calculate value from
indexes

if (midElement == target) {
return true;
} else if (midElement < target) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return false;
}
}
Use code with caution.
Explanation:

Flatten the Matrix: While we don't explicitly flatten the matrix, we calculate low,
high, and mid to simulate indexes of a single sorted array.

Retrieving Elements: Within the binary search, we use mid / n to find the row and
mid % n to find the column in the original matrix.

Binary Search Logic: Standard binary search comparison guides our search for the
target.

Key Points:

O(log(m * n)) Time Complexity: We perform binary search over conceptually all m * n
elements.
Clever Indexing: Mapping 2D matrix coordinates into a conceptually linear sequence
is what makes this work.

####################################################
url:https://leetcode.com/problems/find-first-and-last-position-of-element-in-
sorted-array/description/

problem: Given an array of integers nums sorted in non-decreasing order, find the
starting and ending position of a given target value.

If target is not found in the array, return [-1, -1].

You must write an algorithm with O(log n) runtime complexity.

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8


Output: [3,4]
Example 2:

Input: nums = [5,7,7,8,8,10], target = 6


Output: [-1,-1]
Example 3:

Input: nums = [], target = 0


Output: [-1,-1]

Constraints:

0 <= nums.length <= 105


-109 <= nums[i] <= 109
nums is a non-decreasing array.
-109 <= target <= 109

solution:
Approach: Two Binary Searches

Find Left Boundary: Use binary search to find the leftmost index where the target
can be inserted while maintaining the array's sorted order. If the target is not
found, it doesn't exist in the array.

Find Right Boundary: Similarly, use binary search to find the rightmost index where
the target can be inserted, which essentially means finding the first position of
the number "larger" than the target. Subtract 1 to arrive at the true 'target's
rightmost index.

Code Implementation:

Java

Explain
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};

// Find left boundary (first possible insertion of target)


int leftIndex = findBoundary(nums, target, true);
// Target doesn't exist
if (leftIndex == nums.length || nums[leftIndex] != target) {
return result;
}

// Find right boundary (first insertion of element larger than target)


result[0] = leftIndex;
result[1] = findBoundary(nums, target, false) - 1;

return result;
}

// Helper function for modified binary search


private int findBoundary(int[] nums, int target, boolean findLeft) {
int low = 0;
int high = nums.length;

while (low < high) {


int mid = low + (high - low) / 2;
if (nums[mid] > target || (findLeft && nums[mid] == target)) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
}
Use code with caution.
Explanation:

findBoundary Helper: This function performs a modified binary search to find the
boundaries. The findLeft flag determines if we're searching for the leftmost or
rightmost boundary.
Search Conditions: The conditions in the binary search are specifically tailored to
locate the appropriate insertion points of the target or an element just larger
than target.
Handling Non-Existence: If the left boundary cannot be found or is out of bounds,
the target doesn't exist.
Key Points:

O(log n) Time Complexity: Two binary searches give us logarithmic time complexity.
Conciseness: Using a helper function keeps the core logic of searchRange clean.

#########################################################

url:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/description/
problem: There is an integer array nums sorted in non-decreasing order (not
necessarily with distinct values).

Before being passed to your function, nums is rotated at an unknown pivot index k
(0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ...,
nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example,
[0,1,2,4,4,4,5,6,6,7] might be rotated at pivot index 5 and become
[4,5,6,6,7,0,1,2,4,4].

Given the array nums after the rotation and an integer target, return true if
target is in nums, or false if it is not in nums.

You must decrease the overall operation steps as much as possible.

Example 1:

Input: nums = [2,5,6,0,0,1,2], target = 0


Output: true
Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3


Output: false

Constraints:

1 <= nums.length <= 5000


-104 <= nums[i] <= 104
nums is guaranteed to be rotated at some pivot.
-104 <= target <= 104

Follow up: This problem is similar to Search in Rotated Sorted Array, but nums may
contain duplicates. Would this affect the runtime complexity? How and why?

solution:

Understanding the Problem

The core challenge is that the sorted array has been rotated, making a
straightforward binary search unworkable. Also, due to duplicates, it's harder to
determine which half of the array is guaranteed to be sorted.

Algorithm: A Modified Binary Search Approach

The best approach leverages a variation of binary search to handle duplicates:

Java

Explain
class Solution {
public boolean 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 true; // Found the target
}

// Handling duplicates: The tricky part


if (nums[left] == nums[mid] && nums[right] == nums[mid]) {
left++;
right--; // Shrink the window in a case where we can't determine
sortedness
} else if (nums[left] <= nums[mid]) { // Left half is sorted
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1; // Search left
} else {
left = mid + 1; // Search right
}
} else { // Right half is sorted
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1; // Search right
} else {
right = mid - 1; // Search left
}
}
}

return false; // Target not found


}
}
Use code with caution.
Explanation

Base case: If nums[mid] matches the target, we've found it!


Handling duplicates: If the left, middle, and right elements are equal, we simply
narrow the search window. This deals with scenarios where it's impossible to
definitively know which side is sorted.
Sorted half: Otherwise, we determine which half (left or right) is definitively
sorted.
Search within the sorted range: We strategically narrow our search in a manner
similar to regular binary search based on whether the target falls within the range
of the sorted half.
Follow-up: Runtime Complexity

Worst Case: O(N) due to potential shrinking of the window by just one element in
cases with many duplicates.
Average Case: O(log N), akin to binary search when there are fewer duplicates.

############################################################

url: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
description/

problem:Suppose an array of length n sorted in ascending order is rotated between 1


and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

[4,5,6,7,0,1,2] if it was rotated 4 times.


[0,1,2,4,5,6,7] if it was rotated 7 times.
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the
array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element
of this array.

You must write an algorithm that runs in O(log n) time.


Example 1:

Input: nums = [3,4,5,1,2]


Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Example 2:

Input: nums = [4,5,6,7,0,1,2]


Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Example 3:

Input: nums = [11,13,15,17]


Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times.

Constraints:

n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
All the integers of nums are unique.
nums is sorted and rotated between 1 and n times.

solution:

Logic

The key insight is that in a rotated sorted array, there will always be one half
that remains sorted. Here's how we identify the minimum element:

The minimum element is where the sorted array "breaks".


If nums[mid] is greater than nums[right], the minimum element must lie in the right
half (the unsorted part).
If nums[mid] is less than or equal to nums[right], the minimum element lies in the
left half (including mid since it could be the minimum).
Code Implementation

Java

Explain
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;

while (left < right) {


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

if (nums[mid] > nums[right]) {


left = mid + 1; // Minimum is in the right half
} else {
right = mid; // Minimum could be mid or further left
}
}

return nums[left]; // Or nums[right] - they're the same at this point


}
}
Use code with caution.
Explanation

Initialization: We set left and right pointers to the array's boundaries.


Binary Search: Inside the while loop, we calculate the mid index.
Logic: We compare nums[mid] with nums[right].
If nums[mid] is greater, the "break" (and hence, the minimum) must lie in the right
unsorted half, so we move left.
Otherwise, the minimum lies on the left side or could be mid itself, so we move
right.
Convergence: The loop converges when left and right point to the same element,
which is the minimum.

##################################################################

url:https://leetcode.com/problems/minimum-size-subarray-sum/
problem:
Given an array of positive integers nums and a positive integer target, return the
minimal length of a
subarray
whose sum is greater than or equal to target. If there is no such subarray, return
0 instead.

Example 1:

Input: target = 7, nums = [2,3,1,2,4,3]


Output: 2
Explanation: The subarray [4,3] has the minimal length under the problem
constraint.
Example 2:

Input: target = 4, nums = [1,4,4]


Output: 1
Example 3:

Input: target = 11, nums = [1,1,1,1,1,1,1,1]


Output: 0

Constraints:

1 <= target <= 109


1 <= nums.length <= 105
1 <= nums[i] <= 104

Follow up: If you have figured out the O(n) solution, try coding another solution
of which the time complexity is O(n log(n)).

solution:
Here's the code for finding the minimal length of a subarray whose sum is greater
than or equal to the target in an array of positive integers:
Java

Explain
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int minLength = Integer.MAX_VALUE;
int sum = 0;
int left = 0;

for (int right = 0; right < nums.length; right++) {


sum += nums[right];

while (sum >= target) {


minLength = Math.min(minLength, right - left + 1);
sum -= nums[left];
left++;
}
}

return minLength == Integer.MAX_VALUE ? 0 : minLength;


}
}
Use code with caution.
Explanation:

We initialize minLength to Integer.MAX_VALUE, sum to 0, and left to 0.


We use a for loop to iterate through the nums array from left to right (right
pointer).
Inside the loop, we add the current element nums[right] to sum.
We use a while loop to shrink the window as long as sum is greater than or equal to
target.
Inside the while loop, we update minLength with the minimum length found so far.
We subtract the leftmost element (nums[left]) from sum and increment left to shrink
the window.
After the outer loop, we return minLength. If no subarray satisfies the condition,
minLength will still be Integer.MAX_VALUE, and we return 0.
Time Complexity: O(n), where n is the length of the nums array. This is because we
iterate through the array only once using the two nested loops.

Space Complexity: O(1), as we only use constant extra space to store variables like
minLength, sum, and left.

###########################################################################

url: https://leetcode.com/problems/search-a-2d-matrix-ii/description/
problem:
Write an efficient algorithm that searches for a value target in an m x n integer
matrix matrix. This matrix has the following properties:

Integers in each row are sorted in ascending from left to right.


Integers in each column are sorted in ascending from top to bottom.

Example 1:

Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],


[18,21,23,26,30]], target = 5
Output: true
Example 2:

Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],


[18,21,23,26,30]], target = 20
Output: false

Constraints:

m == matrix.length
n == matrix[i].length
1 <= n, m <= 300
-109 <= matrix[i][j] <= 109
All the integers in each row are sorted in ascending order.
All the integers in each column are sorted in ascending order.
-109 <= target <= 109

solution:
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int rows = matrix.length;
int cols = matrix[0].length;

// Start from the top-right corner


int row = 0;
int col = cols - 1;

while (row < rows && col >= 0) {


if (matrix[row][col] == target) {
return true;
} else if (matrix[row][col] > target) {
col--; // Move left if current element is larger
} else {
row++; // Move down if current element is smaller
}
}

return false; // Target not found


}
}

Explanation:

Understanding the Matrix Structure: Rows are sorted in ascending order from left to
right and columns in ascending order top to bottom.
Starting Point: Begin at the top-right corner. This element gives us some immediate
knowledge:
If matrix[row][col] is less than the target, all elements in the current row are
too small.
If matrix[row][col] is greater than the target, all elements in the current column
are too large.
Smart Movement:
Target Found: If matrix[row][col] matches the target, return true.
Too Large: If the current element is too large, move left (col--) within the same
row.
Too Small: If the current element is too small, move down (row++) within the same
column.
Efficiency:

Time Complexity: O(m + n), where 'm' is the number of rows and 'n' is the number of
columns. In the worst case, we might traverse one complete row and one complete
column.
Key Insight: By starting from the top-right corner, we strategically eliminate
either an entire row or column in each iteration!

#######################################################

url:https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/
problem:
Given an n x n matrix where each of the rows and columns is sorted in ascending
order, return the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct
element.

You must find a solution with a memory complexity better than O(n2).

Example 1:

Input: matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8


Output: 13
Explanation: The elements in the matrix are [1,5,9,10,11,12,13,13,15], and the 8th
smallest number is 13
Example 2:

Input: matrix = [[-5]], k = 1


Output: -5

Constraints:

n == matrix.length == matrix[i].length
1 <= n <= 300
-109 <= matrix[i][j] <= 109
All the rows and columns of matrix are guaranteed to be sorted in non-decreasing
order.
1 <= k <= n2

solution:

Approach

Understanding Value Ranges: The smallest element in the matrix is matrix[0][0], and
the largest is matrix[n-1][n-1]. The kth smallest must lie somewhere between these.
Binary Search on Values: Use binary search on the range of possible values in the
matrix, not on indices. We'll calculate a 'mid' value and count how many elements
in the matrix are less than or equal to this 'mid.'
Counting Elements: To efficiently count elements in the matrix that are less than
or equal to 'mid', start from the top-right corner and traverse the matrix in
reverse sorted order.
Code
Java

Explain
class Solution {
public int kthSmallest(int[][] matrix, int k) {
int n = matrix.length;
int lo = matrix[0][0];
int hi = matrix[n - 1][n - 1];

while (lo < hi) {


int mid = lo + (hi - lo) / 2;
int count = countLessOrEqual(matrix, mid);

if (count < k) {
lo = mid + 1; // Need to find a larger value
} else {
hi = mid; // The answer could be 'mid' or a smaller value
}
}

return lo;
}

// Helper function to count elements <= 'target'


private int countLessOrEqual(int[][] matrix, int target) {
int count = 0;
int n = matrix.length;
int row = n - 1, col = 0;

while (row >= 0 && col < n) {


if (matrix[row][col] > target) {
row--;
} else {
count += row + 1; // All elements in the column will be smaller
col++;
}
}
return count;
}
}
Use code with caution.
Explanation

kthSmallest()
Find the range of potential values using lo and hi.
Iteratively perform binary search within this range.
countLessOrEqual: Helper to count how many elements are less than or equal to a
given 'target'.
countLessOrEqual():
Starts from the top-right corner.
If the current element is larger than the 'target', moves to the left (smaller
numbers).
Otherwise, all elements in the current column are smaller; it adds the count and
moves to the right.
Memory Complexity:

We're not storing the full matrix, using only a constant amount of extra space.
This gives us better memory complexity than O(n²).

You might also like