For one dimensional array, I can implement it by the following way:
def binary_search(a, key, low=0, high=None):
if high is None:
high = len(a) - 1
while low <= high:
mid = (low + high) // 2
midval = a[mid]
if midval < key:
low = mid + 1
elif midval > key:
high = mid - 1
else:
return mid
raise ValueError
Or
def binary_search_bisect(lst, x):
from bisect import bisect_left
i = bisect_left(lst, x)
if i != len(lst) and lst[i] == x:
return i
return -1
For Double Dimensional Array
First way: But this is not a better solution.
1. convert 2D to 1D
lst = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
lst2 = [ j for i in lst for j in i]
2. by binary search to find the value's index in 1D
binary_search_bisect(lst, 6) # search 6 and get its index is 5
3. convert the index of 1D to index of 2D
row = 5 / 5 # 1
col = 5 % 5 # 0
4. Verify the result
lst[1][0] # the result is 6
Second way:
started from top right corner (we can also start from bottom left corner)
and move left if current element is greater than the value to be searched
and bottom if current element is smaller than the value to be searched.
Question:
- How can I implement the second way by python, I have no idea to implement it.
to_double_idxis complicated and inefficient. See step 3 in the OPs first way to see that you can simply use/ widthand% width. Even if for some reason you want to generalize this to allow different lengths of the sublists, you'd better accumulate the lengths once, in the initializer, and then haveto_double_idxbinary search those prefix sums instead of doing your linear enumeration.