zoukankan      html  css  js  c++  java
  • 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]
    ————————————————



  • 相关阅读:
    JSP----获取表单参数
    application 从web.xml中获取初始化参数
    使用定时器分解任务
    无阻塞加载外部js(动态脚本元素,XMLHttpRequest注入,LazyLoad)
    ReactJs 入门DEMO(转自别人)
    带你一分钟理解闭包--js面向对象编程(转载他人)
    使用SqlBulkCopy进行批量数据插入
    AngularJsDEMO
    ECharts
    C#发送邮件DEMO
  • 原文地址:https://www.cnblogs.com/limingqi/p/11787429.html
Copyright © 2011-2022 走看看