Skip to content
41 changes: 41 additions & 0 deletions search_a_2d_matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# https://leetcode.com/problems/search-a-2d-matrix/

# Checking the target element is present in the matrix for this first unpack the matrix into signle dimension and iteration over the each list. while iterating through the list used intial checks like if the last element is greater/less than target and contiued the loop accordingly and once we find the row for the target applied the binary search. Complexity O(m + log n)

# leetcode wants O(log(m*n))

class Solution:
def searchMatrix(self,matrix: list[list[int]], target: int) -> bool:
# unpacking the matrix into the row
for row in matrix:
# best case if the last element is target
if row[-1] == target:
return True
# if last element in the row is smaller than the target it
# will not exist in this row; move on to the next row
elif row[-1] < target:
continue
# if first element in the row is greater than the target it
# will not exist in this row; move on to the next row
elif row[0] > target:
continue

low = 0
high = len(row)-1

# apply the binary search
while low <= high:
mid = (low + high) // 2
# if the mid element is target
if target == row[mid]:
return True
# if the target is less than the mid element shift the pointer to left half
if target < row[mid]:
high = mid - 1
# if the target is greater than the mid element shift the pointer to the right half
else:
low = mid + 1
return False

search = Solution()
print(search.searchMatrix([[1,3,5,7],[10,11,16,20],[23,30,34,60]],34))
44 changes: 44 additions & 0 deletions search_in_a_sorted_array_of_unknown_size.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/description/

# In this problem we need to find the target. This is done by doubling the index till we find the range where the target element is present. Once we find the range we apply the binary search. And find the location of the target element. Complexity O(log n)

# implementing own array reader to test locally
class ArrayReader:
def __init__(self, array = []):
self.array = array

def get(self, index: int):
return self.array[index]

class Solution:
def search (self, reader : ArrayReader, target :int) -> int:
low = 0
high = 1

# reader.get(high) returns the value the index. we are checking that value with the given target
while reader.get(high) < target:
# if the target is greater than the high value double the high index until we find the range of the target
low = high
high *= 2
# dont let low cross the high if it then we have searched already and we didnt get required element
while low <= high:
mid_index = (low + high) // 2
# check the target is equal to the mid_index
if reader.get(mid_index) == target:
return mid_index
# if the target is less than the mid element change the high
if reader.get(mid_index) > target:
high = mid_index - 1
# if the target is greater than the mid element change the low
else:
low = mid_index +1
return -1

op = Solution()

print(op.search(ArrayReader([-1,0,3,5,9,12]),9))
print(op.search(ArrayReader([-1,0,3,5,9,12]),2))




53 changes: 53 additions & 0 deletions search_in_rotated_sorted_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# https://leetcode.com/problems/search-in-rotated-sorted-array/


# In this problem either one part of the binary search is going to be the sorted. So find the mid element at first and check which part is sorted. Once we get the sorted part check the target is present or not and accordingly move the pointer to the either sides. complexity O(log n)


# why we cant do the normal binary search: Because it can be applied on the sorted here and here the one half is not sorted
# that is why we are adding two extra checks and do the binary only in the valid not for the all means we are handeling the situation in such a way that it should check only in the sorted half


# to check whether the left is sorted
# if nums[low] <= nums[mid_index]:
# and its else condition where right is sorted
# second check is if nums[low] <= target < nums[mid_index]: which is sorted half to decide which side to search

class Solution:
def search(self, nums: list[int], target: int) -> int:
# initialising low and high
low = 0
high = len(nums) - 1
# loop till high doesn't cross the low
while low <= high:
# finding the middle index for binary search
mid_index = (low + high) // 2
# first check if the target is equal to middle element no need to iterate left or right part return the mid_index
if target == nums[mid_index]:
return mid_index

# check whether the left side is sorted
if nums[low] <= nums[mid_index]:
# check target is present in the left side
if nums[low] <= target < nums[mid_index]:
# now the target is in left side so move the high pointer to the left because we are considering left range for the search
high = mid_index - 1
# if target is not in the left side then move the low pointer to right side because we are considering right range for the search
else:
low = mid_index + 1
# else the first element is greater than middle means right side sorted
else:
# check target is present in the right side
if nums[mid_index] < target <= nums[high]:
# now the target is in right part so move the mid to the right because we are considering right range for the search
low = mid_index + 1
# if target is not in the right part then move the high pointer to left side because we are considering left range for the search
else:
high = mid_index - 1

return -1

op = Solution()
print(op.search([4,5,6,7,0,1,2], 0))
# Output: 4