day 1 | 二分查找

35 搜索插入位置

题目描述:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。

题解一:左闭右开
class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0
        #右开区间
        right = len(nums)
        #右开区间取不到等号
        while left < right:
            middle = int((left + right)/2)
            if nums[middle] > target:
                right = middle
            elif nums[middle] < target:
                left = middle + 1
            else:
                return middle
        return left
#[1,2,3,4,5,7,8,9,10] 5
题解二:左闭右闭
class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0
        # 右闭
        right = len(nums) - 1
        # 能取到等号
        while left <= right:
            middle = int((left + right)/2)
            if nums[middle] > target:
                # 右闭
                right = middle - 1
            elif nums[middle] < target:
                left = middle + 1
            else:
                return middle
        return left

34 在排序数组中查找元素的第一个和最后一个位置

题目描述:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

题解一:左闭右开
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        left, right = 0, len(nums)
        if not nums:
            return [-1, -1]
        # 循环不变量:
        # nums[left-1] < target
        # nums[right] >= target
        while left < right:
            middle = (left + right) // 2
            if nums[middle] < target:
                left = middle + 1
            else:
                right = middle
        start = left
        left, right = 0, len(nums)
        while left < right:
            middle = (left + right) // 2
            if nums[middle] < target + 1:
                left = middle + 1
            else:
                right = middle
        end = left - 1
        if start == len(nums) or nums[start] != target:
            return [-1, -1]
        # 如果 start 存在,那么 end 必定存在
        return [start, end]
题解二:左闭右闭
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        left, right = 0, len(nums) - 1
        if not nums:
            return [-1, -1]
        while left <= right:
            # 循环不变量:
            # nums[left-1] < target
            # nums[right+1] >= target
            middle = (left + right) // 2
            if nums[middle] < target:
                left = middle + 1
            else:
                right = middle - 1
        start = left
        left, right = 0, len(nums) - 1
        while left <= right:
            middle = (left + right) // 2
            if nums[middle] < target + 1:
                left = middle + 1
            else:
                right = middle - 1
        end = left - 1
        if start == len(nums) or nums[start] != target:
            return [-1, -1]
        # 如果 start 存在,那么 end 必定存在
        return [start, end]

69 x 的平方根

题目描述:

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

题解:闭区间

只能用闭区间,因为如果x=4,x/2=2

class Solution:
    def mySqrt(self, x: int) -> int:
        left, right = 0, x // 2
        while left <= right:
            middle = (left + right) // 2
            if middle ** 2 < x:
                left = middle + 1
            else:
                right = middle - 1
        ans = left if left ** 2 == x else left - 1
        return ans

74 搜索二维矩阵

题目描述:

给你一个满足下述两条属性的 m x n 整数矩阵:

  • 每行中的整数从左到右按非严格递增顺序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。

题解:两次二分法

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        m, n = len(matrix), len(matrix[0])
        left, right = 0, m - 1
        while left <= right:
            middle = (left + right) // 2
            #注意:取右边界target + 1
            if matrix[middle][0] < target + 1:
                left = middle + 1
            else:
                right = middle - 1
        #注意:取右边界left - 1
        row = left - 1
        left, right = 0, n - 1
        while left <= right:
            middle = (left + right) // 2
            if matrix[row][middle] < target:
                left = middle + 1
            else:
                right = middle - 1
        #注意:left < n
        return left < n and matrix[row][left] == target

 33 搜索螺旋排列数组

题目描述:

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

题解:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if not nums:
            return -1
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r) // 2
            if nums[mid] == target:
                return mid
            if nums[0] <= nums[mid]:
                if nums[0] <= target < nums[mid]:
                    r = mid - 1
                else:
                    l = mid + 1
            else:
                if nums[mid] < target <= nums[len(nums) - 1]:
                    l = mid + 1
                else:
                    r = mid - 1
        return -1

复习:

350(简单)

解法一:哈希表

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        dic = {}
        ans = []
        for i in nums1:
            if i in dic.keys():
                dic[i] += 1
            else:
                dic[i] = 1
        for i in nums2:
            if i in dic.keys() and dic[i] > 0:
                dic[i] -= 1
                ans.append(i)
        
        return ans

解法二:排序 + 双指针

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        m, n = len(nums1), len(nums2)
        nums1.sort()
        nums2.sort()
        i, j = 0, 0
        ans = []
        while i < m and j < n:
            if nums1[i] == nums2[j]:
                ans.append(nums1[i])
                i += 1
                j += 1
            elif nums1[i] < nums2[j]:
                i += 1
            else:
                j += 1
        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值