LeetCode C++ 33. Search in Rotated Sorted Array【二分】中等

112 篇文章 0 订阅
52 篇文章 0 订阅

You are given an integer array nums sorted in ascending order, and an integer target .

Suppose that nums is rotated at some pivot unknown to you beforehand (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2] ).

If target is found in the array return its index, otherwise, return -1 .

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

Example 3:

Input: nums = [1], target = 0
Output: -1

Constraints:

  • 1 <= nums.length <= 5000
  • -10^4 <= nums[i] <= 10^4
  • All values of nums are unique.
  • nums is guranteed to be rotated at some pivot.
  • -10^4 <= target <= 10^4

题意:给出一个升序排序的数组和一个整数,这一数组在未知的某个点上进行了旋转,如 [1,2,3,4,5,6,7] 可能变为 [4,5,6,7,1,2,3] 。然后需要在数组中搜索目标值,如果存在则返回它的位置。


解法1 顺序搜索

完全没有利用到数组的特征,直接进行最简单的顺序搜索, O ( n ) O(n) O(n) 的时间复杂度:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        for (int i = 0; i < nums.size(); ++i) if (nums[i] == target) return i;
        return -1;
    }
};

效率如下,比较感人:

执行用时:16 ms, 在所有 C++ 提交中击败了17.24% 的用户
内存消耗:11.3 MB, 在所有 C++ 提交中击败了5.21% 的用户

解法2 找到旋转点

我们可以找到那个旋转点,不是进行数组的恢复(太浪费时间了),而是经过判断,对旋转点的一边进行二分搜索,得到结果。这一算法的整体时间复杂度是 O ( n ) O(n) O(n) ,没有实质的改进。暂时不想写代码。


解法3 利用数组的特征

对于旋转数组,如果将其一分为二,则其中一定有一个是有序的,另一个可能有序也可能无序。对有序部分用二分查找,无序部分再一分为二……这样循环。具体代码如下:

class Solution {
public:
    int search(vector<int>& nums, int target) { 
        int lo = 0, hi = nums.size() - 1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] == target) return mid;
            else if (nums[mid] < nums[hi]) { //右半段是有序的
                if (nums[mid] < target && target <= nums[hi]) lo = mid + 1; //对右半段二分搜索
                else hi = mid - 1; //右半段有序,但不在右半段的范围内,因此对左半段搜索
            } else { //左半段有序
                if (target >= nums[lo] && target < nums[mid]) hi = mid - 1; //对左半段二分搜索
                else lo = mid + 1; //左半段有序,但不在左半段的范围内,因此对右半段搜索
            }
        }
        return -1;
    }
};

提交后效率如下:

执行用时:4 ms, 在所有 C++ 提交中击败了82.70% 的用户
内存消耗:11.2 MB, 在所有 C++ 提交中击败了5.21% 的用户

递归版代码如下:

class Solution {
private:
    int binarySearchInRotatedSortedArray(const vector<int>& a, int l, int r, int t) {
        if (l > r) return -1;
        int mid = l + (r - l) / 2;
        if (a[mid] == t) return mid;
        else if (a[mid] < a[r]) { //右半段有序
            return (a[mid] < t && t <= a[r]) ?
                binarySearchInRotatedSortedArray(a, mid + 1, r, t) : 
                binarySearchInRotatedSortedArray(a, l, mid - 1, t);
        } else { //左半段有序
            return (t < a[mid] && t >= a[l]) ?
                binarySearchInRotatedSortedArray(a, l, mid - 1, t) :
                binarySearchInRotatedSortedArray(a, mid + 1, r, t);
        }
    }
public:
    int search(vector<int>& nums, int target) { 
        return binarySearchInRotatedSortedArray(nums, 0, nums.size() - 1, target);
    }
};

递归版的效率低一些:

执行用时:8 ms, 在所有 C++ 提交中击败了45.60% 的用户
内存消耗:11.4 MB, 在所有 C++ 提交中击败了5.21% 的用户

进阶题目:81. 搜索旋转排序数组 II

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

memcpy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值