minimal absolute value of the difference between A[i] and B[i] (array A is strictly increasing, array B is strictly decreasing)

Question:

Given two sequences A and B of the same length: one is strictly increasing, the other is strictly decreasing.
It is required to find an index i such that the absolute value of the difference between A[i] and B[i] is minimal. If there are several such indices, the answer is the smallest of them. The input sequences are standard Python arrays. It is guaranteed that they are of the same length. Efficiency requirements: Asymptotic complexity: no more than the power of the logarithm of the length of the input sequences.
I have implemented index lookup using the golden section method, but I am confused by the use of floating point arithmetic. Is it possible to somehow improve this algorithm so as not to use it, or can you come up with a more concise solution?

import random
import math
def peak(A,B):
    def f(x):
        return abs(A[x]-B[x])
    phi_inv = 1 / ((math.sqrt(5) + 1) / 2)
    def cal_x1(left,right):
        return right - (round((right-left) * phi_inv))
    def cal_x2(left,right):
        return left + (round((right-left) * phi_inv))
    left, right = 0, len(A)-1
    x1, x2 = cal_x1(left, right), cal_x2(left,right)
    while x1 < x2:
        if f(x1) > f(x2):
            left = x1
            x1 = x2
            x2 = cal_x1(x1,right)
        else:
            right = x2
            x2 = x1
            x1 = cal_x2(left,x2)
    if x1 > 1 and f(x1-2) <= f(x1-1): return x1-2
    if x1+2 < len(A) and f(x1+2) < f(x1+1): return x1+2
    if x1 > 0 and f(x1-1) <= f(x1): return x1-1
    if x1+1 < len(A) and f(x1+1) < f(x1): return x1+1
    return x1

#value check
def make_arr(inv):
    x = set()
    while len(x) != 1000:
        x.add(random.randint(-10000,10000))
    x = sorted(list(x),reverse = inv)
    return x

x = make_arr(0)
y = make_arr(1)
needle = 1000000
c = 0
for i in range(1000):
    if abs(x[i]-y[i]) < needle:
        c = i
        needle = abs(x[i]-y[i])
print(c)
print(peak(x,y))
Asked By: Андрей С.

||

Answers:

Approach

The poster asks about alternative, simpler solutions to posted code.

The problem is a variant of Leetcode Problem 852, where the goal is to find the peak index in a moutain array. We convert to a peak, rather than min, by computing the negative of the abolute difference. Our aproach is to modify this Python solution to the Leetcode problem.

Code

def binary_search(x, y):
    ''' Mod of https://walkccc.me/LeetCode/problems/0852/ to use function'''
    def f(m):
        ' Absoute value of difference at index m of two arrays '
        return -abs(x[m] - y[m])    # Make negative so we are looking for a peak
            
    # peak using binary search
    l = 0
    r = len(arr) - 1

    while l < r:
      m = (l + r) // 2
      if f(m) < f(m + 1):    # check if increasing
        l = m + 1
      else:
        r = m                 # was decreasing

    return l

Test

def linear_search(A, B):
    ' Linear Search Method '
    values = [abs(ai-bi) for ai, bi in zip(A, B)]
    return values.index(min(values))     # linear search
    
def make_arr(inv):
    random.seed(10)    # added so we can repeat with the same data
    x = set()
    while len(x) != 1000:
        x.add(random.randint(-10000,10000))
    x = sorted(list(x),reverse = inv)
    return x


# Create data
x = make_arr(0)
y = make_arr(1)

# Run search methods
print(f'Linear Search Solution {linear_search(x, y)}')
print(f'Golden Section Search Solution {peak(x, y)}') # posted code
print(f'Binary Search Solution {binary_search(x, y)}')

Output

Linear Search Solution 499
Golden Section Search Solution 499
Binary Search Solution 499
Answered By: DarrylG
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.