Leetcode 33 搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
思路:根据中间点和首尾点的数值比较,可以知道哪一半的顺序正常,再判断接下来要丢掉哪哪一半的区间。
class Solution:
def search(self, nums: List[int], target: int) -> int:
#注意数组没有重复元素(简化了问题)
l=0
r=len(nums)-1
while l<=r:
mid = (l+r)//2
if nums[mid]==target:
return mid
if nums[l] <= nums[mid]: #左半边正常
if nums[l] <= target <= nums[mid]:
r = mid-1
else:
l = mid+1
if nums[mid] <= nums[r]: #右半边正常
if nums[mid] <= target <= nums[r]:
l = mid+1
else:
r = mid-1
return -1
Leetcode 35 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
思路:即等价于在数组中寻找第一个大于等于该目标值的数字位置。
- 如果nums[mid] < target 去右边找 left+=1;
- 如果nums[mid] >= target 去左边找 right-=1;
情况1: 左边不再有大于等于目标值的数字,left会一直+1直到回到mid;
情况2:左边还有大于等于目标值的数字
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
#等价于寻找第一个大于等于target的index
l=0
r=len(nums)-1
while l<=r:
mid = (l+r)//2
if nums[mid]<target:
l=mid+1
else:
r=mid-1
return l
Note:如果目标值不存在于数组中,且数组中的每个值都小于数值,返回的left就是数组的长度。
Leetcode 50 Pow(x, n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
思路:二分+递归
class Solution:
def myPow(self, x: float, n: int) -> float:
if x==0 and n<0:
return None
if n<0:
return 1/self.myPow(x,-n)
if n==0:
return 1
if n==1:
return x
mid = self.myPow(x,n//2)
if n%2 == 0:
return mid*mid
else:
return mid*mid*x
Leetcode 29 两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
思路:利用位运算
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
sign = (dividend<0) ^ (divisor<0)
dividend = abs(dividend)
divisor = abs(divisor)
count=0
while dividend > 0:
res = dividend - divisor
if res<0:
break
if res>=0 and res < divisor:
count+=1
break
tmp = divisor
count0 = 1
while tmp <= dividend:
tmp = tmp << 1
count0 = count0 << 1
tmp = tmp >> 1
count0 = count0 >> 1
count+=count0
dividend = dividend - tmp
if sign:
return 0-count
else:
return count