python rotated binary search 二分查找

有一道leetcode题,简单点说,就是一个有序序列,随机截成两段,然后这两段交换位置,让你在O(logn)的时间里找一个search一个值,本质上是二分查找的变异

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.
 

我的解题过程:

  1. 先想,理论上想通了,直接开始干,然后写了半天,发现不对劲
  2. 分析不对劲的原因,基础不牢,地动山摇,所以先写了一份简单的二分查找
  3. 然后回到原来的代码,搞定,通过测试
  4. 查看网络上大牛写的,优化了一份代码
  5. 结果,生成了三份代码

理论

本质上考察的分类讨论的思想,随机截断,交换位置,会出现三种情况,三种情况依次处理,即可得到正确答案

  • 情况一:没有改变顺序,也就是原始序列

  • 情况二:左边多于右边

  • 情况三:左边少于右边

  • 特殊情况:两边相等,由于我取mid的方法,是向下取整,所以,第一次取mid,会落在左边,也就是和情况二相同

为何这么分?对于情况二,第一次取mid的值为5,属于后半截(正常排序的后半截),而对于情况三,第一次取mid的值为1,属于前半截(正常排序的前半截),会导致采取的策略不一样

最终答案

这是最后优化的版本,参考这篇博文写的 

https://blog.csdn.net/ljiabin/article/details/40453607

完整代码可以参考这里:

https://gitee.com/invisibleDes/algorithm/blob/master/rotated_search.py

class BinarySearch():
    
    def search(self, array, target):
        n = len(array)
        if n <= 0:
            return "data error"   
        return self.rotated_binary_search(array, 0 , n-1, target)
        
    def rotated_binary_search(self, a, left , right, target):
        mid = math.floor((left+right)/2)
        if a[left] == target:
            return left
        if a[mid] == target:
            return mid
        if a[right] == target:
            return right

        if a[left] < a[right]:
            if target < a[left] or target > a[right]:
                return "not found"
            elif target < a[mid]:
                return self.rotated_binary_search(a, left+1, mid-1, target)
            else:
                return self.rotated_binary_search(a, mid+1, right-1, target)
        elif a[mid] > a[left]:
            if target < a[mid] and target > a[left]:
                return self.rotated_binary_search(a, left+1, mid-1, target)
            else:
                return self.rotated_binary_search(a, mid+1, right-1, target)
        else:
            if target > a[mid] and target < a[right]:
                return self.rotated_binary_search(a, mid+1, right-1, target)
            else:
                return self.rotated_binary_search(a, left+1, mid-1, target)


def test_c_binary_search():
    bs = BinarySearch()
    print(bs.search([4, 5, 6, 7, 0, 1, 2], 1))
    

if __name__ == "__main__":
    test_c_binary_search()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值