leetcode中二分查找的具体应用

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-1, -1]。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

思路:

一看到算法时间复杂度必须是 O(log n) 级别,肯定想到是二分法。但这里二分法需要变换一下:设置左右两个指针进行二分法,当通过二分法搜寻到目标值时,左右指针合一,然后在合一的位置上分别向左向右遍历寻找是否还有和目标值相等的数.

def test(array,target):

if len(array)==0:
return [-1,-1]
elif target<array[0] or target>array[-1]:
return [-1,-1]
else:
l,r = 0,len(array)-1
while l<=r:
mid = (l+r)//2
if target<array[mid]:
r = mid-1
elif target>array[mid]:
l = mid + 1
else:
l,r=mid,mid
while l-1>=0 and array[l-1]==target:
l=l-1
while r+1<len(array) and array[r+1]==target:
r = r+1
return [l,r]
return [-1,-1]

array = [5,7,7,8,8,10]
t = test(array,8)
print(t)

旋转有序数组寻找最小一个元array = [4,5,1,2,3]


class Solution:
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l = len(nums)
if l == 0:
return None
if l == 1:
return nums[0]

p = nums[0]
#if nums[-1] >= p:
# return p

left, right = 0, l - 1
while left<=right:
mid = (left + right) // 2
if nums[mid]>=nums[left] and nums[mid]<=nums[right]:
value = min(p,nums[left])
break
else:
value = min(p, nums[mid])
if nums[mid]<nums[left]:
right = mid-1
else:
left = mid+1
return value




s=Solution()
t=s.findMin(array)
print(t)

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
注意数组中可能存在重复的元素。
示例 1:
输入: [1,3,5]
输出: 1
示例 2:
输入: [2,2,2,0,1]
输出: 0

这题是寻找旋转严格升序数组中最小值的升级版,主要是解决碰到[2,2,2,0,2]和[2,0,2,2,2]这种情况时该怎么移动指针的问题。注意最后一个else不能是left += 1,因为这样严格单调递增函数会取得最大值。

class Solution:
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
left, right = 0, len(nums)-1
while left < right:
mid = (left+right)//2
if nums[mid] > nums[right]:
left = mid +1
elif nums[mid] < nums[left]:
right = mid
else:
right = right - 1
return nums[left]

不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。


class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(len(nums)):
if nums[abs(nums[i])]<0:
return abs(nums[i])
else:
nums[abs(nums[i])] = -nums[abs(nums[i])]

第一种思路:

线性扫描数组,遇到第一个count > 1 的元素就把它返回。


class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for item in nums:
if nums.count(item) != 1:
return item

3.寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
li = nums1 + nums2
while len(li) > 2:
li.remove(max(li))
li.remove(min(li))
return sum(li) / len(li)
---------------------------------------


class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
nums = nums1 + nums2
nums.sort()
length = len(nums)
if length == 2:
return (nums[0] + nums[1])/2
if length % 2 == 0:
return (nums[length // 2 - 1] + nums[(length // 2)])/2
return nums[length // 2]
————————————————



原文地址:https://www.cnblogs.com/limingqi/p/11787429.html