使用二分查找找到元素出现的首位置和尾位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
from typing import List
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
size = len(nums)
if size == 0:
return [-1, -1]
first_position = self.__find_first_position(nums, size, target)
if first_position == -1:
return [-1, -1]
last_position = self.__find_last_position(nums, size, target)
return [first_position, last_position]
def __find_first_position(self, nums, size, target):
left = 0
right = size - 1
while left < right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] == target:
right = mid
else:
# nums[mid] > target
right = mid - 1
if nums[left] == target:
return left
else:
return -1
def __find_last_position(self, nums, size, target):
left = 0
right = size - 1
while left < right:
mid = (left + right + 1) // 2
if nums[mid] > target:
right = mid - 1
elif nums[mid] == target:
left = mid
else:
# nums[mid] < target
left = mid + 1
# 由于能走到这里,说明在数组中一定找得到目标元素,因此这里不用再做一次判断
return left
合并两个有序链表
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
def find_last_position(nums, left, right, target):
# 寻找第一个大于target的位置
if nums[left]>target:
return left
while left < right:
mid = (left + right) // 2
if nums[mid] > target:
right = mid
elif nums[mid] == target:
right = mid
else:
# nums[mid] < target
left = mid + 1
# 由于能走到这里,说明在数组中一定找得到目标元素,因此这里不用再做一次判断
if nums[right]<target:
return right+1
return right
i=0
for j in range(n):
a=nums2[j]
i=find_last_position(nums1,i,m+j-1,a)
#print(a,i)
#把a插入到nums1[i]
for k in range(m+n-1,i,-1):
nums1[k]=nums1[k-1]
nums1[i]=a
#print(nums1)
当然也可以用传统的双指针法
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
# Make a copy of nums1.
nums1_copy = nums1[:m]
nums1[:] = []
# Two get pointers for nums1_copy and nums2.
p1 = 0
p2 = 0
# Compare elements from nums1_copy and nums2
# and add the smallest one into nums1.
while p1 < m and p2 < n:
if nums1_copy[p1] < nums2[p2]:
nums1.append(nums1_copy[p1])
p1 += 1
else:
nums1.append(nums2[p2])
p2 += 1
# if there are still elements to add
if p1 < m:
nums1[p1 + p2:] = nums1_copy[p1:]
if p2 < n:
nums1[p1 + p2:] = nums2[p2:]
有序矩阵查找
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m=len(matrix)
n=len(matrix[0])
#二分查找,把矩阵看做一维升序list即可
recordrow=0
for i in range(m):
if matrix[i][0]==target or matrix[i][n-1]==target:
return True
elif matrix[i][0]<target and matrix[i][n-1]>target:
recordrow=i
break
def search(matrix,a,left,right,recordrow):
#print(recordrow,left,right)
if left>right:
return False
if left==right:
if matrix[recordrow][left]==a:
return True
else:
return False
mid=(left+right)//2
#print(recordrow,mid)
if matrix[recordrow][mid]==a:
return True
elif matrix[recordrow][mid]>a:
return search(matrix,a,left,mid-1,recordrow)
elif matrix[recordrow][mid]<a:
return search(matrix,a,mid+1,right,recordrow)
return False
return search(matrix,target,0,n-1,recordrow)