Python 每日一练 二分查找 搜索旋转排序数组 详解

简介: Python 每日一练 二分查找 搜索旋转排序数组 详解

大一在读 大数据管理与应用专业 欢迎交流


备战蓝桥杯 倒计时71天


目前主要学习Python算法与数据结构 今日主题:二分查找


算法人算法魂 算法题让我们敢于挑战自己做意想不到的事情


如果还没接触过二分查找的可以看一下小郑上一篇博客保证入门简简单单(有模板)(属于优化版 适用很多场景 但今天这道题用起来就相形见绌了)


今天这个二分写法与上面的模板有所不同 是最基本的写法👇很简单对吧

#核心框架

while a<=b:
    mid=(a+b)//2
    if nums[mid]==target:
        return mid
    elif nums[mid]>target:
        b=mid-1
    else:
        a=mid+1

👇👇现在来让我们试试手


问题描述:

image.png


如果你觉得比较难?先看看这种方法


Python 自带函数解法:index函数用法传送门

Python List index()方法 | 菜鸟教程 (runoob.com)

https://www.runoob.com/python/att-list-index.html


class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return nums.index(target) if target in nums else -1

image.png

二分查找法:


你肯定会说 ''这是无序的!!   二分查找只能用于有序数组 ''


对的 二分查找的确只能用于有序数组

但是审题后我们会发现:nums是由升序数组旋转得到(旋转规则根据题意可知)

先说结论 旋转后的数组 指针定在任意一个位置 那么两段序列中至少有一段是升序的

                                                   (我知道你有点不完全相信我!!)


但事实就是如此:

image.png


第一行是未旋转的升序序列 第二行是旋转后的


当指针指向中间 有两段升序序列


当指针指向右边(2)2到n-1是升序的 n到2不是升序的 因此有一段升序序列


当指针指向左边(n+1)n到n+1是升序的 n+1到n-1不是升序的 因此有一段升序序列


所以说明上面的结论是正确的 (或许你可能觉得我这样证明还不严谨)


那下面给出严格证明:假设数列元素>2个 (一个旋转了还是本身)


设k为分界点 下标0-k升序 下标k-len(nums)-1升序 对数列进行旋转


旋转后 指针指向k 旋转数列有两段升序序列 指向<k的位置 k左半边是有序


指向>k的位置 k右半边是有序   证明完毕


代码设计思路:拿到旋转后的数组  划分区域:有序的 无序的

对有序的二分查找 如果找到 大功告成

如果找不到 返回第一步 再次对第一轮的无序区域划分有序区域和无序区域

发现了吗?这其实就是一个递归的过程 因此我们设置两个指针l和r 用来递归每一次的无序区间 😀


class Solution:
    def search(self, nums: List[int], target: int) -> int:
        def Binary_search(l,r,target):
            if l==r and nums[l]!=target:return -1  
            mid=(l+r)//2#至少有一段是完全递增的
            if nums[mid]<nums[l]:#有序区间在右,对其对分查找
                a,b=mid,r
                while a<=b:
                    middle=(a+b)//2
                    if nums[middle]==target:
                        return middle
                    elif nums[middle]>target:
                        b=middle-1
                    else:
                        a=middle+1
                return Binary_search(l,mid-1,target)#如果右有序区间没找到 去找左无序区间
            else:#有序区间在左,对其对分查找
                a,b=l,mid
                while a<=b:
                    middle=(a+b)//2
                    if nums[middle]==target:
                        return middle
                    elif nums[middle]>target:
                        b=middle-1
                    else:
                        a=middle+1
                return Binary_search(mid+1,r,target)#如果左有序区间没找到 去找右无序区间
        return Binary_search(0,len(nums)-1,target)

image.png

好啦 今天的每日一练就到这里 祝大家新年快乐😀和小郑一起加油  


目录
相关文章
|
vr&ar
leetcode每日一题 2021/4/7 81. 搜索旋转排序数组 II
leetcode每日一题 2021/4/7 81. 搜索旋转排序数组 II
42 0
|
4月前
|
算法 索引 Python
【Leetcode刷题Python】33. 搜索旋转排序数组
解决LeetCode "搜索旋转排序数组" 问题的Python实现代码。代码使用了二分查找算法,首先检查目标值是否存在于数组中,然后通过比较数组中间值与数组首尾值来确定应该在数组的哪一半继续搜索,直到找到目标值或搜索范围为空。如果找到目标值,返回其索引;如果搜索结束仍未找到,返回 -1。
23 0
|
4月前
|
索引 Python
【Leetcode刷题Python】35. 搜索插入位置
解决在排序数组中查找目标值并返回其索引或插入位置的问题的Python实现代码。
26 0
|
4月前
|
算法 Python
【Leetcode刷题Python】74. 搜索二维矩阵
两种解决LeetCode "搜索二维矩阵" 问题的方法的Python实现。第一种方法是从二维矩阵的右上角开始线性搜索,通过比较当前元素与目标值来决定搜索方向。第二种方法是将二维矩阵视为一维数组进行二分查找,通过计算中间元素的行列索引来更新搜索区间。两种方法都旨在高效地判断目标值是否存在于给定的有序二维矩阵中。
46 0
|
4月前
|
算法 索引 Python
【Leetcode刷题Python】34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)
解决LeetCode "在排序数组中查找元素的第一个和最后一个位置" 问题的方法。第一种方法是使用两次二分查找,首先找到目标值的最左边界,然后找到最右边界。第二种方法是利用Python的list.index()方法,先正序找到起始位置,再逆序找到结束位置,并给出了两种方法的Python实现代码。
70 0
|
6月前
|
存储 算法 数据挖掘
LeetCode第33题:搜索旋转排序数组【python】
LeetCode第33题:搜索旋转排序数组【python】
|
6月前
|
存储 算法 数据挖掘
LeetCode 题目 81:搜索旋转排序数组 II
LeetCode 题目 81:搜索旋转排序数组 II
|
7月前
|
Rust Java Go
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
64 0
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
|
7月前
|
Python Go Java
Golang每日一练(leetDay0027) 单词搜索、删除有序数组中的重复项 II、搜索旋转排序数组 II
Golang每日一练(leetDay0027) 单词搜索、删除有序数组中的重复项 II、搜索旋转排序数组 II
67 0
Golang每日一练(leetDay0027) 单词搜索、删除有序数组中的重复项 II、搜索旋转排序数组 II
|
7月前
|
Python Java Go
Python每日一练(20230430) 移除元素、删除排序链表中的重复元素、搜索旋转排序数组II
Python每日一练(20230430) 移除元素、删除排序链表中的重复元素、搜索旋转排序数组II
76 0
Python每日一练(20230430) 移除元素、删除排序链表中的重复元素、搜索旋转排序数组II