Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary Search 2 Completed #1923

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Find 1st and Last Element Position in Sorted Array Question
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
34. Find First and Last Position of Element in Sorted Array {Medium}

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
36 changes: 36 additions & 0 deletions Find Min in Rotated Sorted Array Question
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
153. Find Minimum in Rotated Sorted Array {Medium}

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.
28 changes: 28 additions & 0 deletions Find Peak Element Question
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
162. Find Peak Element {Medium}

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.
93 changes: 93 additions & 0 deletions Find1stLastPositionOfElementSortedArr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Time Complexity:
O(log n): Both binarySearchFirst and binarySearchLast functions are O(log n) since they each perform binary search.
Overall: The algorithm has an overall time complexity of O(log n + log n) = O(2log n) = O(log n), making it efficient for large arrays.

Space Complexity
O(1): This solution only uses a fixed amount of space for variables, making the space complexity constant.

eg: 1,2,3,3,3,4,5,6,7,8,8
Element: 3
1st pos: 2
Last pos: 4
*/
class Find1stLastPositionOfElementSortedArr {
public int[] searchRange(int[] nums, int target)
{
if(nums.length ==0) return new int[]{-1, -1}; //If no elements present, means target not found so return.

/*
We will be doing two binary search, one for finding the first index, and next for last index. For first index search, we will be searching the
whole array, if first index is not found means target not present
*/

int first = binarySearchFirst(nums, target, 0, nums.length-1);
if(first == -1)
return new int[]{-1, -1};

int last = binarySearchLast(nums, target, first, nums.length-1);
return new int[]{first, last};
}

private int binarySearchFirst(int[] nums, int target, int low, int high)
{
while(low<=high)
{
int mid = low+(high-low)/2;

//If mid is the target
if(nums[mid]==target) //we found the element, but not the first index
{
if(mid==0 || nums[mid-1] != nums[mid]) //IF mid = 0 means it is the first index so mid-1 won't exist
{
return mid; //first index is the middle element
}
else {
high = mid-1; //So we move the pointer to left to find the start of the element which is first index
}
}
else if(nums[mid]>target)
{
//Sorted array so search the left part of the array
high = mid-1;
}
else {
//Searching the right part of the arrray
low = mid+1;
}
}

return -1;
}

private int binarySearchLast(int[] nums, int target, int low, int high)
{
while(low<=high)
{
int mid = low+(high-low)/2;

//If mid is the target
if(nums[mid]==target) //we found the element, but not the first index
{
if(mid==nums.length-1 || nums[mid] != nums[mid+1]) //IF mid = n-1 means it is the last index so mid+1 won't exist
{
return mid; //last index is the middle element
}
else {
low = mid+1; //So we move the pointer to right to find the last index of the element
}
}
else if(nums[mid]>target)
{
//Sorted array so search the left part of the array
high = mid-1;
}
else {
//Searching the right part of the arrray
low = mid+1;
}
}

return -1;
}
}
55 changes: 55 additions & 0 deletions FindMinRotatedSortedArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Time Complexity:
The time complexity is O(logn), where n is the number of elements in the nums array.
This complexity comes from the binary search approach used to find the minimum element. Each iteration divides the search space by half,
so the number of comparisons required is logarithmic with respect to the size of the array.

Space Complexity:
The space complexity is O(1).
The algorithm only uses a fixed amount of extra space (for the variables len, low, high, and mid), regardless of the input size.
There are no data structures like arrays or lists being used to store intermediate results, so the space complexity remains constant.

Property of a rotated sorted array is the minimum element would always lie in the unsorted part of the array

In a rotated sorted array, there is a portion that seems "unsorted" because of the rotation. The minimum
element will always lie in this "unsorted" part, where the rotation caused a break in the usual order.
This is what makes it possible to identify the minimum element as the point where the rotation occurred.
*/
class FindMinRotatedSortedArray {
public int findMin(int[] nums) {

int len = nums.length;
int low = 0, high = len - 1;

while(low<=high)
{
//We can check if the array is already sorted, which means low will point to minimum element
// if(nums[low]<=nums[high])
// return nums[low];

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

//Checking edge case, if mid is the min element, eg: 7,0,1 so elements on both sides will be greater than mid
if((mid == 0 || nums[mid-1] > nums[mid]) && (mid == len-1 || nums[mid+1] > nums[mid]))
return nums[mid];

/*
If we don't want to check initially if the array is already sorted or not, which means start of the array has the min element, then in such case
we need to start with checking if the array is right sorted and then eliminate the right part and then move to check if it is a left sorted array or not.
Or if we still want to start eliminating the left sorted array first, and check the right part of array for min element. Then we need to, check the initial
steps if the array is already sorted or not
*/

else if(nums[mid] <= nums[high]) //right sorted array
{
high = mid-1;
}
else {
low = mid+1;
}

}

return -1;
}
}
50 changes: 50 additions & 0 deletions FindPeakElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Time Complexity:
The time complexity of this algorithm is O(log n), where n is the number of elements in the nums array.
In each iteration, binary search halves the search space by adjusting either low or high, depending on whether the peak might lie on the left or the right side of mid.
Halving the search space repeatedly leads to a logarithmic time complexity, O(log n).

Space Complexity:
The space complexity of this algorithm is O(1) (constant space).
It uses only a fixed amount of extra space for the variables low, high, and mid.
No additional data structures or recursive calls are used, so the space used by the algorithm does not increase with the size of the input array nums.

nums[i] != nums[i + 1] for all valid i.
Elements can be repeated, but it is not consecutive and an array is not sorted.
eg: -INFINITY [1,2,1,3,5,6,4] -INFINITY => correct input
-INFINITY [1,1,2,3,5,6,4] -INFINITY => incorrect input

Peak element => element greater than both its neighbors.

For edge elements, don't compare with right member if it is the last element and don't compare
it with left member if it is the first element
*/
class FindPeakElement {
public int findPeakElement(int[] nums) {

int n = nums.length;
int low = 0, high = n-1;

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

/*
If mid id the peak,it is greater than adjacent elements, we will not use >= because we cannot have same consecutive elements
No need to check mid if it is the corner element.
*/
if((mid == 0 || nums[mid] > nums[mid-1]) && (mid==n-1 || nums[mid] > nums[mid+1]))
return mid;

else if(mid>0 && nums[mid]<nums[mid-1]) //check if we have a greater slope on left path
{
high=mid-1;
}
else {
low = mid+1;
}
}

return -1;
}
}
47 changes: 47 additions & 0 deletions FindPeakElementIndirectBinarySearch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Time Complexity: O(log n)
Space Complexity: O(1)

In this code, the binary search loop condition while (low < high) ensures that the loop terminates as soon as low and high converge
to a single index, where the peak element exists. The reason low <= high causes a Time Limit Exceeded (TLE) error is because it
creates an infinite loop. Let's go over why that happens.

Explanation:
With low < high:
This condition terminates the loop as soon as low equals high.
At that point, low (or high, since they are the same) points to the peak element, and the loop breaks.
With low <= high:
If we change the condition to low <= high, the loop might never terminate.
In each iteration, either low is set to mid + 1 or high is set to mid.
When low equals high, both low and high will point to the same index, which is the peak element.
However, the condition low <= high allows the loop to continue even when low == high.
Inside the loop, mid is calculated as low + (high - low) / 2, which will also be low (or high since they’re the same).
This results in an infinite loop because neither low nor high changes anymore.
Solution:
To avoid this issue and allow the loop to terminate correctly, we keep the condition as low < high. This way, the loop will stop once
low and high point to the same element, which is the peak. After the loop ends, we can return low or high (they’re the same at this point),
which is the index of the peak element.
*/
class FindPeakElementIndirectBinarySearch {
public int findPeakElement(int[] nums) {

int n = nums.length;
int low = 0, high = n-1;

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

//We will not be checking the mid to check if it the peak, we will not be having any base logic
if(nums[mid]<nums[mid+1])
{
low = mid+1;
}
else {
high=mid; //here we are not sure if mid is the peak or not, so we include the element hence high=mid and not mid-1
}
}

return low;
}
}