Skip to content
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
58 changes: 58 additions & 0 deletions SearchInA2DMatrix_SingleBinarySearch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Time Complexity : O(log(m*n)). m is the number of rows and n is the number of columns
// Space Complexity : O(1) as we do not use any extra space

// Did this code successfully run on Leetcode : yes
// Any problem you faced while coding this : no

/*
* Problem: Search in a 2D array
*/

/*
* Approach: Single Binary Search on 2D array(by treating it as a 1D array)
* In this approach, we perform binary search on the 2D array imagining it as a 1D array. We start by
* setting the left and right pointers to the start and end of the array. We simply retrieve
* the exact row and column by performing div and modulus operations on the mid index by number of columns.
* If we find the target at this location we return true or else we discard the portions of 2D array we are not interested in.
* We keep repeating the binary search on the included portion until we find the target.
* At the end, if we don't find one, we return false.
*/
public class SearchInA2DMatrix_SingleBinarySearch {
public boolean searchMatrix(int[][] matrix, int target) {
// We return false if matrix is null or empty
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}

int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m * n - 1;
int mid, midValue;

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

int r = mid / n;
int c = mid % n;
midValue = matrix[r][c];

if (target == midValue) return true;
else if (target < midValue) right = mid - 1;
else left = mid + 1;
}

return false;
}

// Driver code
public static void main(String[] args) {
int[][] matrix = {{1,3,5,7},{10,11,16,20},{23,30,34,60}};
int target1 = 3;
int target2 = 100;

SearchInA2DMatrix_SingleBinarySearch searchInA2DMatrix = new SearchInA2DMatrix_SingleBinarySearch();
System.out.println(searchInA2DMatrix.searchMatrix(matrix, target1));
System.out.println(searchInA2DMatrix.searchMatrix(matrix, target2));
}
}
77 changes: 77 additions & 0 deletions SearchInA2DMatrix_TwoBinarySearches.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Time Complexity : O(log m + log n) ~ O(log(m*n)). m is the number of rows and n is the number of columns
// Space Complexity : O(1) as we do not use any extra space

// Did this code successfully run on Leetcode : yes
// Any problem you faced while coding this : no

/*
* Problem: Search in a 2D array
*/

/*
* Approach: Two Binary Searches
* In the following approach, we leverage the fact that the columns and rows both are in the strict
* increasing order. We apply binary searches twice, first over the rows to find the target row and
* second over the columns in a row found as a result of first binary search to locate the exact position of target.
* If we fail to locate the target within any row or column, we return false;
*/

public class SearchInA2DMatrix_TwoBinarySearches {
public boolean searchMatrix(int[][] matrix, int target) {
// We return false if matrix is null or empty
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}

int m = matrix.length;
int n = matrix[0].length;

// binary search to find the row
int startRow = 0;
int endRow = m-1;
int rowFound = -1;

while (startRow <= endRow) {
int midRow = startRow + (endRow - startRow)/2;
if (target >= matrix[midRow][0] && target <= matrix[midRow][n-1]) {
rowFound = midRow;
break;
} else if (target < matrix[midRow][0]) {
endRow = midRow - 1;
} else {
startRow = midRow + 1;
}
}

if (rowFound == -1) {
return false;
}

// binary search to find the column in the correct row
int startCol = 0;
int endCol = n-1;
while (startCol <= endCol) {
int midCol = startCol + (endCol - startCol)/2;
if (matrix[rowFound][midCol] == target) {
return true;
} else if (matrix[rowFound][midCol] < target) {
startCol = midCol + 1;
} else {
endCol = midCol - 1;
}
}

return false;
}

// Driver code
public static void main(String[] args) {
int[][] matrix = {{1,3,5,7},{10,11,16,20},{23,30,34,60}};
int target1 = 3;
int target2 = 100;

SearchInA2DMatrix_TwoBinarySearches searchInA2DMatrix = new SearchInA2DMatrix_TwoBinarySearches();
System.out.println(searchInA2DMatrix.searchMatrix(matrix, target1));
System.out.println(searchInA2DMatrix.searchMatrix(matrix, target2));
}
}
65 changes: 65 additions & 0 deletions SearchInARotatedSortedArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Time Complexity : O(log n) as we keep dividing the search space into two halves
// Space Complexity : O(1) as we do not use any auxiliary space
// Did this code successfully run on Leetcode : yes
// Any problem you faced while coding this : no

/*
* Problem: Search In a Rotated Sorted Array
* Approach: Binary Search
* In this approach, we perform a binary search on nums array. Since, the array is rotated, we expect one of the halves
* to be completely sorted. In order to find which side is sorted, we check the if the element at the left index is smaller than
* or equal to the element at mid which means they are sorted. If not, it is safe to say that the right portion is sorted.
* Within the sorted array, we check if the target is within the range. Depending upon target falls in the range or not, we
* move the left and right pointers to select the correct portion of array. We keep repeating the binary search until left and
* right pointers do not cross each other.
*
*/
public class SearchInARotatedSortedArray {
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[left] <= nums[mid]) {
// left side is sorted
if (nums[left] <= target && nums[mid] >= target) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
// right side is sorted
if (nums[mid] <= target && nums[right] >= target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
}

return -1;
}

// Driver code
public static void main(String[] args) {
int[] nums1 = {4, 5, 6, 7, 0, 1, 2};
int target1 = 0;

int[] nums2 = {1};
int target2 = 0;

SearchInARotatedSortedArray searchInARotatedSortedArray = new SearchInARotatedSortedArray();

int result1 = searchInARotatedSortedArray.search(nums1, target1);
System.out.println(result1);

int result2 = searchInARotatedSortedArray.search(nums2, target2);
System.out.println(result2);
}
}
51 changes: 51 additions & 0 deletions SearchInASortedArrayOfUnknownSize.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Time Complexity : O(log n) where n is the index of the target value provided
// Space Complexity : O(1) as we do not use any extra space
// Did this code successfully run on Leetcode : yes
// Any problem you faced while coding this : no

/*
* Problem: Search in a sorted array of unknown size
* Approach: Boundary definition and binary search
*
* In this approach, before applying binary search, we need to define boundaries for search space. We use a low and high
* pointer to locate the target. Until the target falls within the range of [low, high], we keep increasing our search
* space by setting the low pointer to high and doubling high. Once target falls in a specific [low, high] range, we
* know that all elements are sorted in the range and we can apply binary search on that range to find the exact position
* of target.
*/

// This is ArrayReader's API interface.
// You should not implement it, or speculate about its implementation
interface ArrayReader {
public int get(int index);
}

public class SearchInASortedArrayOfUnknownSize {
public int search(ArrayReader reader, int target) {
int low = 0;
int high = 1;

while (reader.get(high) <= target) {
low = high;
high *= 2;
}

while (low <= high) {
int mid = low + (high - low) / 2;
int midValue = reader.get(mid);
if (midValue == target) {
return mid;
} else if (midValue < target) {
// search in the right part
low = mid + 1;
} else {
// search in the left part
high = mid - 1;
}
}

return -1;
}
}