二分查找

使用二分查找找到元素出现的首位置和尾位置

给定一个按照升序排列的整数数组 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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值