力扣刷题23

第一题:搜索旋转排序数组

来源: https://leetcode.cn/problems/search-in-rotated-sorted-array/description/

题目:

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

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= 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) 的算法解决此问题。

python 复制代码
class Solution:
    def search(self, nums: list[int], target: int) -> int:
        left, right = 0, len(nums) - 1
        
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target:
                return mid
            
            # 左半部分有序
            if nums[left] <= nums[mid]:
                # target 在左半部分的有序区间内
                if nums[left] <= target < nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            # 右半部分有序
            else:
                # target 在右半部分的有序区间内
                if nums[mid] < target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
        
        return -1

这个题让我们查找target所在位置的索引,且题目中要求时间复杂度为O(logn),所以我想到的是二分法。虽然这个数组是旋转有序(比如4,5,6,1,2,3,但它的局部仍然是有序的 ,二分法的核心就是利用有序性缩小查找范围,这个场景刚好能适配。

二分法的本质是"分治"思路,就是每次把查找范围缩小一半,直到找到目标或者确定目标不存在。

核心条件是数组必须是有序的,可以是升序也可以是降序。

基本步骤:

初始化左指针left = 0,初始化右指针right = len(nums) - 1,覆盖整个数组;

循环:当覆盖范围有效,即left right,计算中间位置mid = (left + right) // 2,然后比较numsmid与target,如果相等,就是找到了目标,直接返回mid,否则分两种情况:当numsmid > target时,目标在左半部分,调整右指针right = mid - 1;当numsmid < target时,目标在右半部分,调整左指针left = mid + 1,假如循环结束后仍然没有找到答案,就返回-1。


举个例子模拟一下,以nums = 4,5,6,7,0,1,2,target = 0为例:

初始left = 0,right = 6,mid = 3,numsmid = 7 ,不等于target,numsmid > target, 0 < 7,且左半部分有序,但0不在此部分内,所以left = 4;

此时,left = 4,right = 6,mid = 5,numsmid = 1,numsmid > target,0 < 1,且 右半部分有序,但0也不在此部分内,所以right = 4;

此时left = 4,right = 4,mid = 4,numsmid = 0,numsmid == target,返回mid = 4。

与示例所给结果一致。

ok,记录完毕。


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

来源: https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

题目:

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

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

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

python 复制代码
from typing import List

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        def find_left():
            left, right = 0, len(nums) - 1
            while left <= right:
                mid = (left + right) // 2
                if nums[mid] < target:
                    left = mid + 1
                else:
                    right = mid - 1
            if left < len(nums) and nums[left] == target:
                return left
            else:
                return -1

        def find_right():
            left, right = 0, len(nums) - 1
            while left <= right:
                mid = (left + right) // 2
                if nums[mid] > target:
                    right = mid - 1
                else:
                    left = mid + 1
            if right >= 0 and nums[right] == target:
                return right
            else:
                return -1

        left_pos = find_left()
        if left_pos == -1:
            return [-1, -1]
        right_pos = find_right()
        return [left_pos, right_pos]

根据题目提示,时间复杂度为O(logn),所以我想到的还是二分法。原理和上一题一样,搞定,记录完毕。

相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法