二分查找

二分查找

标准模板:

n = len(nums)
left = 0
right = n-1
while left <= right:
	#这种写法的原因是为了防止right和left数据过大时造成溢出
    mid = left + (right-left)//2
    if nums[mid]==target:
        return mid
    elif nums[mid]<target:
        left = mid+1
    elif nums[mid]>target:
        right = mid-1
#这种写法的left最后是要比right大一的比如说[3,2],left可能不在nums范围内
return left

快速幂

class Solution:
    def myPow(self, x: float, n: int) -> float:
        a = 1
        flag = 1
        if n<0:
            flag = 0
            n = abs(n)
        while n:
            if n&1:
                a = a*x
            n >>=1
            x = x*x
        return a if flag else 1/a

开平方:(二分法)

class Solution:
    def mySqrt(self, x: int) -> int:
        left = 0
        right = x-1
        if x<2:
            return x
        while left<=right:
            mid = left + (right-left)//2
            if mid*mid==x:
                return mid
            elif mid*mid<x:
                left = mid+1
            elif mid*mid>x:
                right = mid-1
        return right 

搜索旋转排序数组:(高级应用)

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。
示例 1:
输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
示例 2:
输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false

class Solution:
    def search(self, nums: List[int], target: int) -> bool:        
        l=0
        r=len(nums)-1
        while(l<=r):
            mid=(l+r)//2
            if(nums[mid]==target):
                return True
            if(nums[mid]==nums[l]==nums[r]):
                l+=1
                r-=1
            elif(nums[mid]>=nums[l]):
                if(nums[l]<=target<nums[mid]):
                    r=mid-1
                else:
                    l=mid+1
            else:
                if(nums[mid]<target<=nums[r]):
                    l=mid+1
                else:
                    r=mid-1
        return False

二分查找target的左侧边界:

n = len(nums)
left = 0
right = n-1
while left <= right:
	#这种写法的原因是为了防止right和left数据过大时造成溢出
    mid = left + (right-left)//2
    if nums[mid]==target:
        right = mid-1
    elif nums[mid]<target:
        left = mid+1
    elif nums[mid]>target:
        right = mid-1
#检查出界情况
if(left>=n or nums[left] != target):
	return -1
#这种写法的left最后是要比right大一的比如说[3,2],left可能不在nums范围内
return left

计算右侧小于当前元素的个数(了解一下二分插排的用法)

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
示例:
输入: [5,2,6,1]
输出: [2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.

import bisect
class Solution:
    def countSmaller(self, nums: List[int]) -> List[int]:
        re_nums = nums[::-1]
        bi_arr = []
        res = []
        for _ in re_nums:
            #插入_数字时在数组中的位置
            pos = bisect.bisect_left(bi_arr, _)
            res.append(pos)
            #插入_
            bisect.insort_left(bi_arr, _)
        return res[::-1]

你可能感兴趣的:(算法,二分法,python,算法,leetcode,数据结构)