diff --git a/search-2D-matrix.py b/search-2D-matrix.py new file mode 100644 index 00000000..3c2ec38d --- /dev/null +++ b/search-2D-matrix.py @@ -0,0 +1,43 @@ +""" +https://leetcode.com/problems/search-a-2d-matrix/description/ + +The matrix looks like a row-wise flattened sorted 1D array. A “flattened sorted array” matrix is globally sorted when laid out as a 1D array from top-left to bottom-right. +--> Integers in each row are sorted left to right (or right to left). +--> The first integer of each row is greater than the last integer of the previous row. +We can treat it as a 1D array of m*n elements. 2D to 1D mapping --> +row = index // n (columns) --> How many full rows before this index as after every n elements, a new row starts +col = index % n --> How far into that row + +Column-wise flattened array will not have the pre-requisite where the first integer of each col is greater than the last integer of the previous col. So, it is not globally sorted when flattened and we cannot use binary search to find an element. 2D to 1D mapping --> +row = index % m (rows) +col= index // m + +Time Complexity: O(logmn) +Space Complexity: O(1) +""" + +class Solution: + def searchMatrix(self, matrix, target): + m = len(matrix) + n = len(matrix[0]) + low = 0 + high = (m*n) - 1 + + while low <= high: # searching for element, so include low == high, which means a single element list + mid = (low + high)//2 + row = mid // len(matrix[0]) + col = mid % len(matrix[0]) + + if matrix[row][col] == target: + return True + elif target > matrix[row][col]: + low = mid + 1 + elif target < matrix[row][col]: + high = mid - 1 + return False + + +matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]] +target = 3 +sol = Solution() +print(sol.searchMatrix(matrix, target)) \ No newline at end of file diff --git a/search-rotated-sorted-array.py b/search-rotated-sorted-array.py new file mode 100644 index 00000000..9dd94c98 --- /dev/null +++ b/search-rotated-sorted-array.py @@ -0,0 +1,52 @@ +""" +https://leetcode.com/problems/search-in-rotated-sorted-array/description/ + +A classical binary search dies because the array isn’t globally sorted, but one of the two halves around mid always is sorted. At each step we can decide: +Which half is sorted? +If nums[L] <= nums[M], left side is sorted; else the right side is sorted. +Is target inside that sorted half’s range? +If yes, shrink into that half; otherwise dive into the other half. + +Same logic is applied when the array is reverse sorted. + +Edge cases: +empty array +length 1 +target equals 1st, last or mid element + +Time Complexity:O(logn) +Space Complexity: O(1) +""" + +class Solution: + def search(self, nums, target): + if len(nums) == 0: + return -1 + + low = 0 + high = len(nums) - 1 + + while low <= high: + mid = (high + low)//2 + + if nums[mid] == target: + return mid + + if nums[low] <= nums[mid]: #LHS is sorted + if nums[low] <= target < nums[mid]: #searching in sorted LHS + high = mid - 1 + else: + low = mid + 1 #switch to unsorted RHS + else: + if nums[mid] <= nums[high]: #RHS is sorted + if nums[mid] < target <= nums[high]: #searching in sorted RHS + low = mid + 1 + else: + high = mid - 1 #switch to unsorted LHS. + return -1 + + +nums = [4,5,6,7,0,1,2] +target = 3 +sol = Solution() +print(sol.search(nums, target)) \ No newline at end of file diff --git a/search-sorted-array-unknown-size.py b/search-sorted-array-unknown-size.py new file mode 100644 index 00000000..709c0eec --- /dev/null +++ b/search-sorted-array-unknown-size.py @@ -0,0 +1,37 @@ +""" +https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/description/ + +Sorted array of unknown size. You don't know the length of the array. Brute force is linear probe but the length of array can be too large. +Exponential Search --> optimal search. Find the boundaries. + +Edge case: +1. element not present +2. 1 element + +Time Complexity: O(2logp) = O(logp) where p is the position of the target +Space Complexity: O(1) +""" + +class Solution: + def search(self, reader, target): + low = 0 + high = 1 + + # O(logp) + while reader.get(high) < target: # Find the search boundaries using exponential search + low = high + high = high * 2 # You double the size of the search range. You cut the number of steps needed in half, compared to walking linearly. + + # O(logp) + while low <= high: # Binary Search on the boundaries + mid = (low + high)//2 + + if reader.get(mid) == target: + return mid + + if target > reader.get(mid): + low = mid + 1 + + if target < reader.get(mid): + high = mid - 1 + return -1 \ No newline at end of file