无限级数最后一次出现

问题描述 投票:0回答:2

您将获得一个无限大(或具有非常大的未知大小)的排序数组。您必须编写一段代码来打印最后一次出现的元素。

输入

输入的第一行包含空格分隔的整数,表示排序数组的元素。 输入的第二行代表要查找的目标元素。

限制

数组可能有重复的元素,即元素不是严格递增的。

输出

打印目标元素的最后一次出现,否则打印-1。

输入样本
1 2 7 7 14 19 23
7
输出示例

3

我无法处理最后一个索引中存在的元素。

def binarySearch(target,arr,start,end):
    mid = (start+end)//2
    if start>end:
        return -1
    elif arr[mid] == target:
        if arr[mid] == arr[-1]:
            return mid
        elif arr[mid+1] != target:
            return mid
        else:
            return mid+1
    elif arr[mid] > target:
        return binarySearch(target,arr,start,mid-1)
    elif arr[mid] < target:
        return binarySearch(target,arr,mid+1,end)

def finiteRange(target,arr,start,end):
    while arr[end]<target:
        start = end
        end *= 2

    return binarySearch(target,arr,start,end)

arr = list(map(int,input().split()))
target = int(input())

result = finiteRange(target,arr,0,1)
print(result)
python binary-search
2个回答
0
投票

对代码进行轻微修改(在注释中)以找到最后一次出现的情况,效果很好。试试这个。

import random


def binarySearch(target,arr,start,end):
    mid = (start+end)//2
    check_value = arr[mid]
    if start>end:
        return -1
    elif check_value == target:
        if arr[mid] == arr[-1] or arr[mid+1] != target:  # check if last occurrence
            return mid
        else:
            return binarySearch(target, arr, mid+1, end)  # recursive call to find last occurrence
    elif check_value > target:
        return binarySearch(target,arr,start,mid-1)
    elif check_value < target:
        return binarySearch(target,arr,mid+1,end)


def finiteRange(target,arr,start,end):
    check_val = arr[start]
    while check_val <= target:  # changed < to <= since we're searching for last occurrence
        start = end
        end *= 2
        try:
            check_val = arr[end]
        except IndexError:
            return -1
    return binarySearch(target,arr,start,end)


# original example produces correct output
arr = list(map(int,input().split()))
target = int(input())
result = finiteRange(target,arr,0,1)
print(result)
# 1 2 7 7 14 19 23
# 7
# 3

# checking with a larger array
target = 50
arr = sorted([random.randint(25, 100) for _ in range(1000)] + [target])

result = finiteRange(target,arr,0,1)
print(result)

0
投票

这里有一些问题:

  • finiteRange
    中,没有检查
    end
    是否为有效索引,即
    arr[end]
    可能会引发异常。例如,检查输入 [1, 2, 3, 7] 和目标 7。当您指示不允许使用
    len
    时,那么您应该捕获错误并仍然调用
    binarySearch

  • finiteRange
    中,循环条件有
    arr[end] < target
    ,这也意味着如果这两个相等,则循环退出,但是您可能会错过
    arr[end+1]
    也可能等于目标的事实,并且拨打
    binarySearch
    的电话将会错过。

  • 不是问题,但由于

    finiteRange
    仅被调用一次,因此它不应该将
    start
    end
    作为参数。相反,这些可以在函数本身中初始化。

  • 如果在

    binarySearch
    中,您在索引
    mid
    处找到了目标,并且发现该目标也在列表末尾找到,您仍然返回
    mid
    ,而
    mid
    可能不是该目标的索引列表中的最后一个元素。此外,如果不允许您使用
    len
    ,那么我会假设
    arr[-1]
    也不被允许。更重要的是,这个 last 条目的索引可能比
    end
    大得多,但您的二分搜索应该只考虑范围
    start
    -
    end

  • 当您发现索引

    mid
    mid+1
    处的值都是目标值时,您会执行
    return mid+1
    而无需检查该目标值是否也存在于索引
    mid+2
    处,...等

这个想法是,当您发现左侧值等于目标时,您也会从左侧缩小窗口:二分搜索应该继续。仅当窗口变空时,您才应将其视为基本情况并返回。在这种情况下,如果目标值存在于列表中,则保证

end
索引就是我们需要的。如果列表中不存在,则由 caller(即
finiteRange
)检测并返回 -1。

这是更正后的代码:

def binarySearch(target, arr, start, end):
    mid = (start + end) // 2
    if start > end:
        return end
    try:  # Trap the error when `mid` is out of range
        if arr[mid] > target:
            return binarySearch(target, arr, start, mid-1)
        else: # Narrow the search also when the target is found
            return binarySearch(target, arr, mid+1, end)
    except IndexError:  # If `mid` is out of range, we go "left"
        return binarySearch(target, arr, start, mid-1)

def finiteRange(target, arr):
    start = 0  # start/end don't need to be parameters
    end = 1
    try:  # Trap the error when accessing an out of range index
        while arr[end] <= target:  # Continue when equal too
            start = end
            end *= 2
    except IndexError:
        pass  # In this case we stop moving the range
    # Use recursion to find the last index of the greatest value
    #  that is not greater than the target
    i = binarySearch(target, arr, 0, end - 1)
    try:
        # Return that index if that greatest value happens to be the target
        return i if arr[i] == target else -1
    except IndexError: # This happens when the list is empty
        return -1

调用示例:

arr = [1, 2, 3, 8, 9, 9, 10, 10, 10, 10, 11, 12, 13, 13]
target = 13
result = finiteRange(target, arr)  # Don't pass 0 and 1 as arguments
print(result)
© www.soinside.com 2019 - 2024. All rights reserved.