旋转数组中的二分查找

简单版本:数组中的元素互不相同

LeetCode 33. Search in Rotated Sorted Array
领扣 33. 搜索旋转排序数组

【我的思路】
利用153. Find Minimum in Rotated Sorted Array找到旋转数组最小元素的下标,作为偏移量shift,然后使用普通binary search求解,只不过需要变换坐标

【Discuss的思路】
首先检查target是否为nums[left]nums[mid]nums[right],如果存在直接返回

由于二分查找只能在有序的数组上进行,所以需要检查数组的前半段(nums[])和后半段哪一段是有序的

情况1:前半段有序,即nums[left] < nums[mid]成立
1-1:如果target落在前半段,即nums[left] < target < nums[mid](不取等号,因为已经检查过了),则后半部分可以排除,令right = mid - 1
1-2:否则排除前半部分,令left = mid + 1

情况2:否则后半段有序
2-1:如果target落在后半段,即nums[mid] < target < nums[right](不取等号,因为已经检查过了),则前半部分可以排除,令left = mid + 1
2-2:否则排除后半部分,令right = mid - 1

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;

        while( left <= right )
        {
            int mid = left + ( right - left ) / 2;

            if( target == nums[mid] )
                return mid;
            if( target == nums[left] )
                return left;
            if( target == nums[right] )
                return right;

            if( nums[left] < nums[mid] )   // 如果前半段有序
            {
                if( nums[left] < target && target < nums[mid] )
                    right = mid - 1;
                else
                    left = mid + 1;
            }
            else                            // 否则后半段有序
            {
                if( nums[mid] < target && target < nums[right] )
                    left = mid + 1;
                else
                    right = mid - 1;
            }
        }

        return -1;
    }
};

困难版本:数组中的元素有重复

Leetcode 81. Search in Rotated Sorted Array II
领扣 81. 搜索旋转排序数组 II

相比于简单版本,仅仅是增加了处理nums[left]nums[mid]nums[right]三者相等的情况,处理的方式是left++; right—;

此外,第23行的nums[left] <= nums[mid]不能缺少等号,如果缺少则WA(暂时没想明白为什么)

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;

        while( left <= right )
        {
            int mid = left + ( right - left ) / 2;

            if( target == nums[mid] )
                return true;
            if( target == nums[left] )
                return true;
            if( target == nums[right] )
                return true;

            // nums[left]、nums[mid]和nums[right]三者相等
            if( nums[left] == nums[mid] && nums[mid] == nums[right] )
            {
                left++;
                right--;
            }
            else if( nums[left] <= nums[mid] )   // 如果前半段有序
            {
                if( nums[left] < target && target < nums[mid] )
                    right = mid - 1;
                else
                    left = mid + 1;
            }
            else                            // 否则后半段有序
            {
                if( nums[mid] < target && target < nums[right] )
                    left = mid + 1;
                else
                    right = mid - 1;
            }
        }

        return false;
    }
};

猜你喜欢

转载自blog.csdn.net/o0Helloworld0o/article/details/81254515