在O(log n)时间中搜索旋转排序数组

时间:2019-03-28 19:11:40

标签: python python-3.x algorithm data-structures binary-search

我和this problem在leetcode上度过了艰难的时光。

我不得不查找解决方案,因为出于某种原因,我的代码总是会遇到一些问题。当在数组中查找不存在的目标编号时,我拥有的当前代码仍然无限循环。

我正在寻求一些帮助,以帮助您了解是否存在更直观的方法来解决此问题并帮助修复我的代码。

我认为我不需要此行:

if nums[mid] == target or nums[low] == target or nums[high] == target:
            return target

我想知道如何做才能确保如果我有一个由1-3个数字组成的数组,那么我的代码可以找到目标而不必指定此条件语句。这是几个例子

print(search([1, 2, 3], 1))
print(search([1], 1))
print(search([2, 1], 1))

此外,例如print(search([5, 1, 2, 3, 4], 6))这样的例子 我的代码从不返回-1

def search(nums, target):
    low = 0
    high = len(nums)-1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == target or nums[low] == target or nums[high] == target:
            return target
        if nums[mid] <= nums[high]:
            if target > nums[mid] and target <= nums[high]:
                low = mid + 1
            else:
                high = mid - 1
        elif nums[mid] > nums[low]:
            if target >= nums[low] and target < nums[mid]:
                high = mid - 1
            else:
                low = mid+1
    return -1


print(search([1, 2, 3], 1))
print(search([5, 4, 1, 2, 3], 2))
print(search([3, 4, 5, 1, 2], 2))
print(search([1], 1))
print(search([2, 1], 1))
print(search([5, 1, 2, 3, 4], 6))

从遇到类似于我上面的解决方案的多种解决方案开始,人们都说这是O(logn),但是我不明白当我们移动lowhigh时如何1.这使我相信解决方案是最坏的情况O(n)

正在寻找帮助!

2 个答案:

答案 0 :(得分:2)

下面是固定代码。我通过leetcode运行了它,并通过了。

  

运行时:52毫秒,比的Python在线提交的11.16%快   在旋转排序数组中搜索。内存使用率:11.9 MB,小于5.44%   旋转排序数组中用于搜索的Python在线提交的数量。

这是O(log n),因为我们在每次迭代中将问题大小减小了一半。在每次迭代中移动高/低时,我们要么选择数组的右半边,要么选择数组的左半边。
所以您的数组大小会像这样减小; n, n/2, n/4, ..., 1,每次将其减半,需要log n步才能从n1

class Solution(object):
def search(self, nums, target):
    low = 0
    high = len(nums)-1
    while low <= high:
        mid = (low + high) // 2
        print(low,high,mid)

        if nums[mid] == target:
            return mid
        elif high==low:
            return -1
        elif nums[mid] <= nums[low] and nums[mid] <= nums[high] and nums[mid-1] >= nums[mid]:#mid is pivot

            if target <= nums[high]:
                low = mid + 1
            else:
                high = mid - 1
        elif nums[mid] > nums[mid-1] and nums[high] > nums[mid]: #pivot to left of mid\
            if nums[mid] > nums[low]: #pivot at start index

                if target < nums[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:
                if target > nums[mid] and target <= nums[high]:
                    low = mid + 1
                elif target < nums[mid] or target >= nums[low]:
                    high = mid - 1
                else:
                    return -1
        elif nums[mid] >= nums[low] and nums[high] <= nums[mid]: #pivot to right of mid
            if target <= nums[high] or target > nums[mid] :
                low = mid + 1
            else:
                high = mid - 1
        else:
            return -1
    return -1

答案 1 :(得分:2)

这里是一个稍有不同的版本

def search(nums, target):
    low = 0
    high = len(nums)-1

    while low <= high:

        mid = (low + high) // 2

        l = nums[low]
        m = nums[mid]
        h = nums[high]

        if target == l:
            return low

        if target == m:
            return mid

        if target == h:
            return high

        if any([
            l < m < h and target < m,
            l == m < h and target > m,
            l > m < h and target > l and target > m,
            l > m < h and target < l and target < m,
            l < m > h and target > l and target < m
        ]):
            high = mid

        elif any([
            l < m < h and target > m,
            l > m < h and target > m and target < h,
            l < m > h,
        ]):
            low = mid

        elif target < l or target > h:
            break

        elif l == m == h:
            break

        else:
            raise Exception("This is not possible, only if some values are reverse/unordered!")

    return -1

使用此数据进行测试(第一列是目标,第二列是列表,第三列是结果索引):

  -10 [1]                      -1
    1 [1]                       0
   22 [1]                      -1
  -10 [1, 2]                   -1
    1 [1, 2]                    0
    2 [1, 2]                    1
   22 [1, 2]                   -1
  -10 [2, 1]                   -1
    1 [2, 1]                    1
    2 [2, 1]                    0
   22 [2, 1]                   -1
  -10 [1, 5]                   -1
    1 [1, 5]                    0
    5 [1, 5]                    1
   22 [1, 5]                   -1
  -10 [5, 1]                   -1
    1 [5, 1]                    1
    5 [5, 1]                    0
   22 [5, 1]                   -1
  -10 [1, 2, 3]                -1
    1 [1, 2, 3]                 0
    2 [1, 2, 3]                 1
    3 [1, 2, 3]                 2
   22 [1, 2, 3]                -1
  -10 [3, 1, 2]                -1
    1 [3, 1, 2]                 1
    2 [3, 1, 2]                 2
    3 [3, 1, 2]                 0
   22 [3, 1, 2]                -1
  -10 [2, 3, 1]                -1
    1 [2, 3, 1]                 2
    2 [2, 3, 1]                 0
    3 [2, 3, 1]                 1
   22 [2, 3, 1]                -1
  -10 [1, 5, 10]               -1
    1 [1, 5, 10]                0
    5 [1, 5, 10]                1
    2 [1, 5, 10]               -1
   10 [1, 5, 10]                2
   22 [1, 5, 10]               -1
  -10 [10, 1, 5]               -1
    1 [10, 1, 5]                1
    5 [10, 1, 5]                2
    2 [1, 5, 10]               -1
   10 [10, 1, 5]                0
   22 [10, 1, 5]               -1
  -10 [5, 10, 1]               -1
    1 [5, 10, 1]                2
    5 [5, 10, 1]                0
    2 [1, 5, 10]               -1
   10 [5, 10, 1]                1
   22 [5, 10, 1]               -1
  -10 [1, 2, 3, 4]             -1
    1 [1, 2, 3, 4]              0
    2 [1, 2, 3, 4]              1
    3 [1, 2, 3, 4]              2
    4 [1, 2, 3, 4]              3
  -10 [1, 2, 3, 4]             -1
  -10 [4, 1, 2, 3]             -1
    1 [4, 1, 2, 3]              1
    2 [4, 1, 2, 3]              2
    3 [4, 1, 2, 3]              3
    4 [4, 1, 2, 3]              0
  -10 [4, 1, 2, 3]             -1
  -10 [3, 4, 1, 2]             -1
    1 [3, 4, 1, 2]              2
    2 [3, 4, 1, 2]              3
    3 [3, 4, 1, 2]              0
    4 [3, 4, 1, 2]              1
  -10 [3, 4, 1, 2]             -1
  -10 [2, 3, 4, 1]             -1
    1 [2, 3, 4, 1]              3
    2 [2, 3, 4, 1]              0
    3 [2, 3, 4, 1]              1
    4 [2, 3, 4, 1]              2
  -10 [2, 3, 4, 1]             -1
  -10 [1, 5, 8, 22]            -1
    1 [1, 5, 8, 22]             0
    5 [1, 5, 8, 22]             1
    8 [1, 5, 8, 22]             2
   22 [1, 5, 8, 22]             3
   10 [1, 5, 8, 22]            -1
  100 [1, 5, 8, 22]            -1
  -10 [22, 1, 5, 8]            -1
    1 [22, 1, 5, 8]             1
    5 [22, 1, 5, 8]             2
    8 [22, 1, 5, 8]             3
   22 [22, 1, 5, 8]             0
   10 [22, 1, 5, 8]            -1
  100 [22, 1, 5, 8]            -1
  -10 [8, 22, 1, 5]            -1
    1 [8, 22, 1, 5]             2
    5 [8, 22, 1, 5]             3
    8 [8, 22, 1, 5]             0
   22 [8, 22, 1, 5]             1
   10 [8, 22, 1, 5]            -1
  100 [8, 22, 1, 5]            -1
  -10 [5, 8, 22, 1]            -1
    1 [5, 8, 22, 1]             3
    5 [5, 8, 22, 1]             0
    8 [5, 8, 22, 1]             1
   22 [5, 8, 22, 1]             2
   10 [5, 8, 22, 1]            -1
  100 [5, 8, 22, 1]            -1
    5 [5, 1, 2, 3, 4]           0
    1 [5, 1, 2, 3, 4]           1
    2 [5, 1, 2, 3, 4]           2
    3 [5, 1, 2, 3, 4]           3
    4 [5, 1, 2, 3, 4]           4
    5 [4, 5, 1, 2, 3]           1
    1 [4, 5, 1, 2, 3]           2
    2 [4, 5, 1, 2, 3]           3
    3 [4, 5, 1, 2, 3]           4
    4 [4, 5, 1, 2, 3]           0
    5 [3, 4, 5, 1, 2]           2
    1 [3, 4, 5, 1, 2]           3
    2 [3, 4, 5, 1, 2]           4
    3 [3, 4, 5, 1, 2]           0
    4 [3, 4, 5, 1, 2]           1
    5 [2, 3, 4, 5, 1]           3
    1 [2, 3, 4, 5, 1]           4
    2 [2, 3, 4, 5, 1]           0
    3 [2, 3, 4, 5, 1]           1
    4 [2, 3, 4, 5, 1]           2
    5 [5, 77, 1, 2, 3]          0
   77 [5, 77, 1, 2, 3]          1
    1 [5, 77, 1, 2, 3]          2
    2 [5, 77, 1, 2, 3]          3
    3 [5, 77, 1, 2, 3]          4
    5 [5, 6, 1, 2, 3]           0
    6 [5, 6, 1, 2, 3]           1
    1 [5, 6, 1, 2, 3]           2
    2 [5, 6, 1, 2, 3]           3
    3 [5, 6, 1, 2, 3]           4
    5 [5, 6, 1, 2, 3, 4]        0
    6 [5, 6, 1, 2, 3, 4]        1
    1 [5, 6, 1, 2, 3, 4]        2
    2 [5, 6, 1, 2, 3, 4]        3
    3 [5, 6, 1, 2, 3, 4]        4
    4 [5, 6, 1, 2, 3, 4]        5

之所以不是 O(n) ,是因为在 O(n) 这意味着算法的性能会随着数据的增加而线性下降,而在这种情况下,性能会随着输入数据的增加以对数方式下降,因为对于每次迭代,我们将数据集均分为较小的较小。