给定长度为 N 的有序整数列表,确定元素 x 是否在列表中
Given a sorted list of integers of length N, determine if an element x is in the list
要解决的问题是:
Given a sorted list of integers of length N, determine if an element x is in the list without performing any multiplication, division, or bit-shift operations. Do this in O(log N) time.
我已经使用修改后的二进制搜索解决了这个问题,但我不确定这是否满足所需的时间复杂度。有更好的解决方案吗?
def get_mid(start, end):
mid = start + 1
sum_ = start + end
prev = mid
while mid < end and (mid + mid) != sum_ and (mid + mid + 1) != sum_:
prev = mid
mid += mid
if mid > end:
return prev
return mid
def bin_search(arr, x):
start, end = 0, len(arr) - 1
while start <= end:
mid = get_mid(start, end)
if mid == 1:
return x in arr[:end]
if x > arr[mid]:
start = mid + 1
elif x < arr[mid]:
end = mid - 1
else:
return True
return False
如果x
的索引存在,我们可以通过逐位构造索引找到它:
def find_idx_sorted(arr, x):
powers_of_two = [1]
while powers_of_two[-1] < len(arr):
powers_of_two.append(powers_of_two[-1] + powers_of_two[-1])
idx = 0
for pot in reversed(powers_of_two):
if idx + pot < len(arr) and x >= arr[idx + pot]:
idx += pot
return idx
那么我们需要做的就是:
def contains_sorted(arr, x):
return arr[find_idx_sorted(arr, x)] == x
使用 log2(N) 调用仅通过加法而不使用循环来查找:
def find_pos(step, arr, val):
next = step+step
if next < len(arr):
choose = find_pos(next, arr, val)
else:
choose = step
next = choose + step
if next < len(arr) and arr[next] <= val:
return next
if arr[choose] <= val:
return choose
return 0
def find_val(arr, val):
index = find_pos(1, arr, val)
if arr[index] == val:
print "found %d at %d" % (val, index)
else:
print "%d not found" % (val)
O(logN)时间完成,必须使用二分查找。因此,这里的关键点是找到一种无需乘法、除法和位移位即可除以 2 的方法。
这是一个在恒定时间内执行的函数:
int divideTwo(int x) {
vector<int> bit = {
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0
};
int v = 0;
for (int i = 1; i < bit.size() - 1 && x > 0; ++i) {
if ((x & bit[i]) > 0)
{
v += bit[i - 1];
x -= bit[i];
}
}
return v;
}
要解决的问题是:
Given a sorted list of integers of length N, determine if an element x is in the list without performing any multiplication, division, or bit-shift operations. Do this in O(log N) time.
我已经使用修改后的二进制搜索解决了这个问题,但我不确定这是否满足所需的时间复杂度。有更好的解决方案吗?
def get_mid(start, end):
mid = start + 1
sum_ = start + end
prev = mid
while mid < end and (mid + mid) != sum_ and (mid + mid + 1) != sum_:
prev = mid
mid += mid
if mid > end:
return prev
return mid
def bin_search(arr, x):
start, end = 0, len(arr) - 1
while start <= end:
mid = get_mid(start, end)
if mid == 1:
return x in arr[:end]
if x > arr[mid]:
start = mid + 1
elif x < arr[mid]:
end = mid - 1
else:
return True
return False
如果x
的索引存在,我们可以通过逐位构造索引找到它:
def find_idx_sorted(arr, x):
powers_of_two = [1]
while powers_of_two[-1] < len(arr):
powers_of_two.append(powers_of_two[-1] + powers_of_two[-1])
idx = 0
for pot in reversed(powers_of_two):
if idx + pot < len(arr) and x >= arr[idx + pot]:
idx += pot
return idx
那么我们需要做的就是:
def contains_sorted(arr, x):
return arr[find_idx_sorted(arr, x)] == x
使用 log2(N) 调用仅通过加法而不使用循环来查找:
def find_pos(step, arr, val):
next = step+step
if next < len(arr):
choose = find_pos(next, arr, val)
else:
choose = step
next = choose + step
if next < len(arr) and arr[next] <= val:
return next
if arr[choose] <= val:
return choose
return 0
def find_val(arr, val):
index = find_pos(1, arr, val)
if arr[index] == val:
print "found %d at %d" % (val, index)
else:
print "%d not found" % (val)
O(logN)时间完成,必须使用二分查找。因此,这里的关键点是找到一种无需乘法、除法和位移位即可除以 2 的方法。 这是一个在恒定时间内执行的函数:
int divideTwo(int x) {
vector<int> bit = {
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0
};
int v = 0;
for (int i = 1; i < bit.size() - 1 && x > 0; ++i) {
if ((x & bit[i]) > 0)
{
v += bit[i - 1];
x -= bit[i];
}
}
return v;
}