35 搜索插入位置
题目描述:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n)
的算法。
题解一:左闭右开
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
#右开区间
right = len(nums)
#右开区间取不到等号
while left < right:
middle = int((left + right)/2)
if nums[middle] > target:
right = middle
elif nums[middle] < target:
left = middle + 1
else:
return middle
return left
#[1,2,3,4,5,7,8,9,10] 5
题解二:左闭右闭
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
# 右闭
right = len(nums) - 1
# 能取到等号
while left <= right:
middle = int((left + right)/2)
if nums[middle] > target:
# 右闭
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return left
34 在排序数组中查找元素的第一个和最后一个位置
题目描述:
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target
,返回 [-1, -1]
。你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
题解一:左闭右开
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
left, right = 0, len(nums)
if not nums:
return [-1, -1]
# 循环不变量:
# nums[left-1] < target
# nums[right] >= target
while left < right:
middle = (left + right) // 2
if nums[middle] < target:
left = middle + 1
else:
right = middle
start = left
left, right = 0, len(nums)
while left < right:
middle = (left + right) // 2
if nums[middle] < target + 1:
left = middle + 1
else:
right = middle
end = left - 1
if start == len(nums) or nums[start] != target:
return [-1, -1]
# 如果 start 存在,那么 end 必定存在
return [start, end]
题解二:左闭右闭
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
left, right = 0, len(nums) - 1
if not nums:
return [-1, -1]
while left <= right:
# 循环不变量:
# nums[left-1] < target
# nums[right+1] >= target
middle = (left + right) // 2
if nums[middle] < target:
left = middle + 1
else:
right = middle - 1
start = left
left, right = 0, len(nums) - 1
while left <= right:
middle = (left + right) // 2
if nums[middle] < target + 1:
left = middle + 1
else:
right = middle - 1
end = left - 1
if start == len(nums) or nums[start] != target:
return [-1, -1]
# 如果 start 存在,那么 end 必定存在
return [start, end]
69 x 的平方根
题目描述:
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
题解:闭区间
只能用闭区间,因为如果x=4,x/2=2
class Solution:
def mySqrt(self, x: int) -> int:
left, right = 0, x // 2
while left <= right:
middle = (left + right) // 2
if middle ** 2 < x:
left = middle + 1
else:
right = middle - 1
ans = left if left ** 2 == x else left - 1
return ans
74 搜索二维矩阵
题目描述:
给你一个满足下述两条属性的 m x n
整数矩阵:
- 每行中的整数从左到右按非严格递增顺序排列。
- 每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target
,如果 target
在矩阵中,返回 true
;否则,返回 false
。
题解:两次二分法
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m, n = len(matrix), len(matrix[0])
left, right = 0, m - 1
while left <= right:
middle = (left + right) // 2
#注意:取右边界target + 1
if matrix[middle][0] < target + 1:
left = middle + 1
else:
right = middle - 1
#注意:取右边界left - 1
row = left - 1
left, right = 0, n - 1
while left <= right:
middle = (left + right) // 2
if matrix[row][middle] < target:
left = middle + 1
else:
right = middle - 1
#注意:left < n
return left < n and matrix[row][left] == target
33 搜索螺旋排列数组
题目描述:
整数数组 nums
按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums
在预先未知的某个下标 k
(0 <= k < nums.length
)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(下标 从 0 开始计数)。例如, [0,1,2,4,5,6,7]
在下标 3
处经旋转后可能变为 [4,5,6,7,0,1,2]
。
给你 旋转后 的数组 nums
和一个整数 target
,如果 nums
中存在这个目标值 target
,则返回它的下标,否则返回 -1
。
你必须设计一个时间复杂度为 O(log n)
的算法解决此问题。
题解:
class Solution:
def search(self, nums: List[int], target: int) -> int:
if not nums:
return -1
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
return mid
if nums[0] <= nums[mid]:
if nums[0] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
else:
if nums[mid] < target <= nums[len(nums) - 1]:
l = mid + 1
else:
r = mid - 1
return -1
复习:
解法一:哈希表
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
dic = {}
ans = []
for i in nums1:
if i in dic.keys():
dic[i] += 1
else:
dic[i] = 1
for i in nums2:
if i in dic.keys() and dic[i] > 0:
dic[i] -= 1
ans.append(i)
return ans
解法二:排序 + 双指针
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
m, n = len(nums1), len(nums2)
nums1.sort()
nums2.sort()
i, j = 0, 0
ans = []
while i < m and j < n:
if nums1[i] == nums2[j]:
ans.append(nums1[i])
i += 1
j += 1
elif nums1[i] < nums2[j]:
i += 1
else:
j += 1
return ans