二分查找
标准模板:
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]