• leetcode:33.搜索旋转排序数组


    33.搜索旋转排序数组

    来源:力扣(LeetCode)

    链接: https://leetcode.cn/problems/search-in-rotated-sorted-array/

    整数数组 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) 的算法解决此问题。

    示例 1:

    输入:nums = [4,5,6,7,0,1,2], target = 0
    输出:4
    
    • 1
    • 2

    示例 2:

    输入:nums = [4,5,6,7,0,1,2], target = 3
    输出:-1
    
    • 1
    • 2

    示例 3:

    输入:nums = [1], target = 0
    输出:-1
    
    • 1
    • 2

    解法

    • 遍历:直接遍历元素,看是否能够找到与target相等的元素,并返回下标;
    • 二分法:虽然不是有序,但是部分是有序的,针对有序数组查找元素一般是使用二分查找法;这里需要判断mid落在左边有序数组,还是右边有序数组;然后再去判断target是否落在left-mid的中间,或者mid-right的中间。如果不在,更新left和right;
      能够根据有序的那部分判断出 target 在不在这个部分:
      • 如果 [ l , m i d ] [l, mid] [l,mid] 是有序数组,且 target 的大小满足 [ n u m s [ l ] , n u m s [ m i d ] ] [nums[l], nums[mid]] [nums[l],nums[mid]],应该将搜索范围缩小至 [ l , m i d ] [l, mid] [l,mid],否则在 [ m i d + 1 , r ] [mid + 1, r] [mid+1,r] 中寻找
      • 如果 [ m i d , r ] [mid, r] [mid,r] 是有序数组,且 target 的大小满足 [ n u m s [ m i d ] , n u m s [ r ] ] [nums[mid], nums[r]] [nums[mid],nums[r]],则我们应该将搜索范围缩小至 [ m i d , r ] [mid, r] [mid,r],否则在 [ l , m i d − 1 ] [l, mid-1] [l,mid1] 中寻找

    在这里插入图片描述

    二分法的写法有很多种,注意退出条件,left right的更新方式;

    代码实现

    遍历法

    python实现

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
            n = len(nums)
            if len(nums) == 1:
                if nums[0] == target:
                    return 0
                else:
                    return -1
    
            for i in range(n):
                if nums[i] == target:
                    return i
            return -1        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    c++实现

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            if (n == 1) {
                return nums[0] == target ? 0 : -1;
            }
            for(int i=0; i<n; i++) {
                if (nums[i] == target)
                    return i;
            }
            return -1;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    复杂度分析

    • 时间复杂度: O ( N ) O(N) O(N)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    二分法

    python实现

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
            n = len(nums)
            if n == 1:
                return 0 if nums[0] == target else -1
            
            left = 0
            right = n-1
            while left <= right:
                mid = left + (right-left) // 2
                if nums[mid] == target:
                    return mid
                if nums[left] <= nums[mid]:  # left part
                    if nums[left] <= target <= nums[mid]:
                        right = mid
                    else:
                        left = mid + 1
                elif nums[left] > nums[mid]:  # right part
                    if nums[mid] <= target <= nums[right]:
                        left = mid
                    else:
                        right = mid - 1
            return -1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    c++实现

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            if (n==1) {
                return nums[0] == target ? 0 : -1;
            }
    
            int left = 0;
            int right = n-1;
            while (left <= right) {
                int mid = left + (right-left)/2;
                if (nums[mid] == target)
                    return mid;
    
                if (nums[left] <= nums[mid]) {  // left part 
                        if (nums[left] <= target && target <= nums[mid])
                            right = mid;
                        else
                            left = mid + 1;
                    }
    
                else {  // right part
                        if (nums[mid] <= target && target <= nums[right])
                            left = mid;
                        else
                            right = mid-1;
                    }
            }
            return -1;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    复杂度分析

    • 时间复杂度: O ( l o g N ) O(logN) O(logN)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    参考

  • 相关阅读:
    【LeetCode每日一题】【单调栈】907. 子数组的最小值之和 Java实现
    element-plus组件问题汇总
    手把手教你从零开始腾讯云服务器部署(连接建站教程)
    零售经营“新赛道” ——基于手机银行APP专区调研的客群精细化运营分析报告
    openai的api_key无效
    MobaXterm使用VNC远程显示和控制ubuntu桌面
    解决mysql去掉字段空格:中间空格,左侧空格,右侧空格,两端空格,水平制表符(tab键或者\t)空格,换行键(\n)空格,回车键(Enter键)空格
    std::thread::id如何转换为字符串或整数
    探索Native Plugins:开启大模型的技能之门
    C#线程发展历史
  • 原文地址:https://blog.csdn.net/uncle_ll/article/details/126334593