zoukankan      html  css  js  c++  java
  • [LeetCode] Search in Rotated Sorted Array

    https://leetcode.com/problems/search-in-rotated-sorted-array/

    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.

    solution 1

    如果是一个未经旋转的有序数组,显然可以直接用二分查找来做。经过旋转的数组,其实本质就是两个排序数组,我们可以分别在两个数组中进行二分查找,难点是找到两个数组的分界线,用遍历的方式来寻找分界线复杂度为o(n),显然不是我们期待的solution,其实只要意识到整个数组最左边与最右边两个值的特殊性,我们同样可以使用二分的方式来寻找分界线。代码如下:

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            if (nums.empty()) {
                return -1;
            }
            
            /* without rotating, excute binary search directly */
            int left = 0, right = nums.size() - 1;
            if (nums[left] <= nums[right]) {
                return binarySearch(nums, left, right, target);
            }
            
            /* include two elements at least */
            left = determineBoundary(nums);
            right = left + 1;
            if (nums[0] <= target && target <= nums[left]) {
                return binarySearch(nums, 0, left, target);
            } else if (nums[right] <= target && target <= nums[nums.size() - 1]) {
                return binarySearch(nums, right, nums.size() - 1, target);
            } else {
                return -1;
            }
        }
        
    private:
        int binarySearch(const vector<int> &nums, const int start, const int end, int target) {
            int left = start, right = end, middle;
            
            while (left + 1 < right) {
                middle = (left + right) >> 1;
                if (target == nums[middle]) {
                    return middle;
                } else if (target > nums[middle]) {
                    left = middle;
                } else if (target < nums[middle]) {
                    right = middle;
                }
            }
            
            if (target == nums[left]) {
                return left;
            }
            
            if (target == nums[right]) {
                return right;
            }
            
            return -1;
        }
        
        int determineBoundary(const vector<int> &nums) {
            int leftValue = nums[0], rightValue = nums[nums.size() - 1];
            int left = 0, right = nums.size() - 1, middle;
            
            while (left + 1 < right) {
                middle = (left + right) >> 1;
                
                if (leftValue < nums[middle]) {
                    left = middle;
                }
                
                if (nums[middle] < rightValue) {
                    right = middle;
                }
            }
            
            return left;
        }
    };

    solution 2

    以上的方案我们通过寻找两个排序数组的分界线,从而对其分别使用二分查找来完成搜索。实际上,该题不必如此繁琐,我们可以省去寻找分界线的步骤,直接进行二分查找。代码如下:

    // author: Jian-xin Zhou
    
    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            if (nums.empty()) {
                return -1;
            }
            
            int left = 0, right = nums.size() - 1, middle;
            
            while (left + 1 < right) {
                middle = (left + right) >> 1;
                
                if (target == nums[middle]) {
                    return middle;
                }
                
                if (nums[left] < nums[middle]) {
                    if (nums[left] <= target && target < nums[middle]) {
                        right = middle;
                    } else {
                        left = middle;
                    }
                }
                
                if (nums[middle] < nums[right]) {
                    if (nums[middle] < target && target <= nums[right]) {
                        left = middle;
                    } else {
                        right = middle;
                    }
                }
            }
            
            if (target == nums[left]) {
                return left;
            }
            
            if (target == nums[right]) {
                return right;
            }
            
            return -1;
        }
    };
  • 相关阅读:
    syslog+rsyslog+logstash+elasticsearch+kibana搭建日志收集
    行为型模式(一)
    spring cloud Sleuth
    Java面试题(基础)
    Java笔试题
    Idea创建SpringBoot项目整合Hibernate
    Java中遍历Map的四种方式
    SQL面试题
    Linux入门
    Spring Boot AOP Demo
  • 原文地址:https://www.cnblogs.com/jianxinzhou/p/4522800.html
Copyright © 2011-2022 走看看