寻找第k小数
已知:双数组已排序,求所有元素中第k小(大)的数
该题解法有多种:
1.暴力解法,对所有元素排序,取出第k小数;
2.双指针,从各数组首位开始比较,更小的删除,遍历直到删除k-1个元素,则此时指针指的元素中更小值满足条件;
3.时间复杂度o(log(m+n)),容易想到二分法,结合双指针做法,即每次删除k//2个元素,以下详细说明
#第k小数通用
def getkminnumber(n1:List[int],n2:List[int],k):
#定义更长数列在前
#每一步去除n/2个数
if len(n1) <= len(n2):
n1,n2=n2,n1
if len(n2)==0:
return n1[k-1]
if k == 1:
return min(n1[0],n2[0])
t=min(k//2-1,len(n2)-1)
q=k//2-1+k//2-1-t
if n1[q]<n2[t]:
n1=n1[q+1::]
k=k-q-1
else:
n2 = n2[t+1::]
k=k-t-1
return getkminnumber(n1,n2,k)
#第k大数,需要注意倒序排列与顺序排列的区别(顺序从0到len-1,倒序从-len到-1)
def getkmaxnumber(n1:List[int],n2:List[int],k):
#定义更长数列在前
if len(n1) <= len(n2):
n1,n2=n2,n1
if len(n2)==0:
return n1[-k]
if k == 1:
return max(n1[-1],n2[-1])
t=min(k//2,len(n2))
q=k//2+k//2-t
if n1[-q]<n2[-t]:
n2=n2[:-t]
k=k-t
else:
n1 = n1[:-q]
k=k-q
return getkmaxnumber(n1,n2,k)
#调用
m=len(nums1)
n=len(nums2)
left = getkminnumber(nums1,nums2,(m+n+1)//2)
#print(left)
right=getkmaxnumber(nums1,nums2,(m+n+1)//2)
#print(right)
return (left+right)/2