牛客——二分查找

1.二分查找-I

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
借助了两个指针left和right,取中间的值就可以

class Solution:
    def search(self , nums: List[int], target: int) -> int:
        # write code here
        left,right=0,len(nums)-1
        while left<=right:
            x=(right-left)//2+left
            if nums[x]==target:
                return x
            elif nums[x]<target:
                left+=1
            elif nums[x]>target:
                right-=1
        return -1

2.二分查找-II(有重复数字)

在这里插入图片描述
这个其实只添加了判断是第一次出现的while语句,加了两行代码

class Solution:
    def search(self , nums: List[int], target: int) -> int:
        # write code here
        left,right=0,len(nums)-1
        while left<=right:
            x=(right-left)//2+left
            if nums[x]==target:
                # 保证找到的target是第一次出现
                while x > 0 and nums[x-1] == nums[x]:
                    x-=1
                return x
            elif nums[x]<target:
                left+=1
            elif nums[x]>target:
                right-=1
        return -1

3.二维数组中的查找

在这里插入图片描述
在这里插入图片描述
一个偷懒的简单方法

class Solution:
    def Find(self , target: int, array: List[List[int]]) -> bool:
        # write code here
        for i in array:
            if target in i:
                return True
        return False

在这里插入图片描述
这道题其实和上面是一样的,我们也是用二分来做,但是可以看做是一个二维的二分,因为右下是增大,所以我们要从左下或者右上开始,才能比较好的进行比较。一个控制上下,一个控制左右,并且要一个增一个减,所以需要注意一下开始的起点。

class Solution:
    def Find(self , target: int, array: List[List[int]]) -> bool:
        # 从左下或者右上开始找 因为i和j得一个增一个减 如果左上或右下就不好找了
        # write code here
        n,m=len(array),len(array[0])
        i=0
        j=m-1
        if n*m==0:
            return False
        while i<n and j>=0:
            if target == array[i][j]:
                return True
            elif target > array[i][j]:
                i+=1
            elif target < array[i][j]:
                j-=1
        return False

4.寻找峰值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
爬坡的过程中一定会遇到最大值,同样的,如果找波谷就是找下坡路的最小值

class Solution:
    def findPeakElement(self , nums: List[int]) -> int:
        start,end = 0,len(nums)-1
        while start<end:# 这里其实就是在找最大值
            mid = (start+end)//2
            right = mid + 1
            if nums[mid] >= nums[right]:
                end = mid
            else:
                start = mid+1
        return start

5.数组中的逆序对

在这里插入图片描述
在这里插入图片描述
这个是视频讲的,直接挨着比,然后计数就可以了。找到比当前数小的,那么比当前数大的和该数都可以比现在这个小数大,所以是len+1。然后依次这么做下去,有一点点绕。

class Solution:
    def InversePairs(self , data: List[int]) -> int:
        # write code here
        # 分为两个区间 左边找 右边找 直到全拆完 然后横跨两个区间的
        # [1,2,3,4,5,6,7,0] 中有 1,0 2,0 3,0 ......
        
        #下面这个方法很巧妙 他是直接挨着比 但是比这个小的 比他大的放一堆 比他小的放一堆
        #找到比当前数小的 那么比当前数大的和该数都可以比现在这个小数大 所以是len+1
        #然后再对两个新列表各自作比较
        return self.recur(data)%1000000007
    def recur(self,arr):
        if len(arr) <= 1: return 0
        b,s = [],[]
        res,pre=0,arr[0]
        for n in arr[1:]:
            if n > pre:
                b.append(n)
            else:
                s.append(n)
                res += len(b) + 1
        return res + self.recur(b) + self.recur(s)# 递归一下 找一下后面的东西 一个数一个数的比

6.旋转数组的最小数字

在这里插入图片描述
在这里插入图片描述

class Solution:
    def minNumberInRotateArray(self , rotateArray: List[int]) -> int:
        # write code here
        if len(rotateArray)==0:
            return 0
        elif len(rotateArray)<=2:
            return rotateArray[-1]
        left,right=0,len(rotateArray)-1
        while left<right:
            mid=(left+right)//2
            if rotateArray[left]<rotateArray[right]:
            # 因为是旋转的,所以左边一般都是大于右边的 当左边小于右边了,就说明这就是那个极小值了
                return rotateArray[left]
            elif rotateArray[left]<rotateArray[mid]:
                    left=mid+1
            elif rotateArray[right]>rotateArray[mid]:
                    right=mid
            else :
                left+=1
        return rotateArray[right]

7.比较版本号

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
变成列表来做,一个一个的比,如果长度小了,就直接补0

class Solution:
    def compare(self , version1: str, version2: str) -> int:
        # write code here
        nums1 = version1.split('.')
        nums2 = version2.split('.')
        n1, n2 = len(nums1), len(nums2)# 这个是按照.分开的,所以可以把0分开 直接int就可以让他变成一个整数了
        # 满足条件就跳出 不满足就一直循环 直到结尾
        for i in range(max(n1, n2)):
            i1 = int(nums1[i]) if i < n1 else 0# 位数不够的时候直接添加0
            i2 = int(nums2[i]) if i < n2 else 0
            if i1 != i2:
                return 1 if i1 > i2 else -1
        return 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值