zoukankan      html  css  js  c++  java
  • [LeetCode]25. Search in Rotated Array旋转数组查找I

    Suppose a sorted array 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).

    You are given a target value to search. If found in the array return its index, otherwise return -1.

    You may assume no duplicate exists in the array.

    解法1:顺序查找,时间复杂度O(n)。

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

    解法2:旋转数组是分为两个有序数组,因此可以使用二分查找。若数组首元素小于数组尾元素,则数组没有旋转,直接使用二分查找binarySearch即可;否则(1)初始化left=0,right=n-1,取mid=(left+right)/2;(2)如果target==nums[mid],则直接返回mid;否则若nums[left]<nums[mid],说明nums[left, ..., mid-1]是有序的,而nums[mid+1, ... , n-1]是旋转的,对前者调用binarySearch,若没找到再对后者调用search;若nums[left]>nums[mid],说明nums[left, ..., mid-1]是旋转的,而nums[mid+1, ... , n-1]是有序的,对后者调用binarySearch,若没找到再对前者调用search。

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            if (n < 2)
                return n == 1 ? (target == nums[0] ? 0 : -1) : -1;
    
            int res, left = 0, right = n - 1;
            if (nums[left] < nums[right])
                res = binarySearch(nums, left, right, target);
            else
            {
                int mid = (left + right) >> 1;
                if (target == nums[mid])
                    res = mid;
                else if (nums[left] < nums[mid])
                {
                    if ((res = binarySearch(nums, left, mid - 1, target)) == -1)
                    {
                        vector<int> tmp(nums.begin() + mid + 1, nums.end());
                        res = search(tmp, target);
                        res = res == -1 ? -1 : res + mid + 1;
                    }
                }
                else
                {
                    if ((res = binarySearch(nums, mid + 1, right, target)) == -1)
                    {
                        vector<int> tmp(nums.begin(), nums.begin() + mid);
                        res = search(tmp, target);
                    }
                }
            }
            return res;
        }
    private:
        int binarySearch(vector<int>& nums, int left, int right, int key)
        {
            if (left > right)
                return -1;
    
            int mid = (left + right) >> 1;
            if (key == nums[mid])
                return mid;
            else if (key > nums[mid])
                return binarySearch(nums, mid + 1, right, key);
            else
                return binarySearch(nums, left, mid - 1, key);
        }
    };

    上面的代码可以进一步优化。首先根据nums[mid]和nums[right]的关系可以确定数组的哪部分是有序的:如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的。然后再根据有序部分首尾两个数字和target的大小关系来判断target存在于哪一部分。

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            int res = -1, left = 0, right = n - 1;
            
            while(left <= right)
            {
                int mid = (left + right) >> 1;
                if(target == nums[mid])
                {
                        res = mid;
                        break;
                }
                else if(nums[mid] < nums[right]) //后半部分有序
                {
                    if(target > nums[mid] && target <= nums[right])
                        left = mid + 1;
                    else
                        right = mid - 1;
                }
                else //前半部分有序
                {
                    if(target >= nums[left] && target < nums[mid])
                        right = mid - 1;
                    else
                        left = mid + 1;
                }
            }    
            return res;
        }
    };

    或者nums[mid]和nums[left]比较也可以,但是要注意mid=left的情况得单独拿出来讨论

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            int res = -1, left = 0, right = n - 1;
            
            while(left <= right)
            {
                int mid = ((left + right) >> 1);
                if(target == nums[mid])
                {
                        res = mid;
                        break;
                }
                else if(nums[mid] > nums[left]) //前半部分有序
                {
                    if(target >= nums[left] && target < nums[mid])
                        right = mid - 1;
                    else
                        left = mid + 1;
                }
                else if(nums[mid] < nums[left]) //后半部分有序
                {
                    if(target > nums[mid] && target <= nums[right])
                        left = mid + 1;
                    else
                        right = mid - 1;
                }
                else //nums[mid]==nums[left]的情况,包括mid=left和存在重复值两种情况
                    left++;
            }
            return res;
        }
    };
  • 相关阅读:
    14.5.5 Creating a File-Per-Table Tablespace Outside the Data Directory
    14.5.5 Creating a File-Per-Table Tablespace Outside the Data Directory
    php session 管理
    php session 管理
    CURD特性
    RabbitMQ学习总结(1)——基础概念详细介绍
    RabbitMQ学习总结(1)——基础概念详细介绍
    RabbitMQ学习总结(1)——基础概念详细介绍
    Java基础学习总结(39)——Log4j 1使用教程
    Java基础学习总结(39)——Log4j 1使用教程
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/4875771.html
Copyright © 2011-2022 走看看