33. 搜索旋转排序数组

Posted ashoftime

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了33. 搜索旋转排序数组相关的知识,希望对你有一定的参考价值。

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

  • 有序 查找 往二分查找上靠
  • 虽然该数组被旋转导致整体无序,但从中间截断后至少有一半仍然是有序的
  • 注意等号

  从mid处划分,至少有一半是有序的。如果target在有序部分的区间内,可使用二分查找进行查找,如果没有找到直接返回-1。但如果target不在有序部分的区间内,并不能直接得出没有找到target的结论,因为有可能被旋转到了无序的区间。

  每次在有序区间里找target,如果找到返回,如果没有找到,继续把无序区间一分为二,然后在新的有序区间寻找。

package binSearch;

public class search_33 {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int mid = (left+right)/2;

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

            //左边有序
            if (nums[mid]>nums[left]){

                //先在有序区间里找
                //目标值在有序范围内
                if (target<=nums[mid] && target>=nums[left]){
                    return  binSea(nums, left, mid, target);
                }

                //有序区间没有再去无序区间找
                left = mid+1;

            }else {
                //右边有序
                if (target>nums[mid]&&target<nums[right]){
                    return binSea(nums,mid,right,target);
                }
                right=mid-1;
            }
        }


        return -1;
    }

    public int binSea(int[]nums,int left,int right,int target){
        int mid;
        while (left<=right){
            mid = (left+right)/2;
            if (nums[mid]==target){
                return mid;
            }else if (nums[mid]>target){
                right = mid-1;
            }else {
                left = mid+1;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {4, 5, 6, 7, 0, 1, 2};
        int target = 9;
        search_33 fun = new search_33();
        int result = fun.search(arr, target);
        System.out.println(result);
    }
}

 

  旋转数组还有一种变体,即数组中可能存在重复的值。此时就不能根据mid与左右端点的值来判断左区间和右区间是否是有序的,例如 1 3 1 1 1 1,此时mid为1,mid==left,但左区间并不是有序的。为此,当mid==left的时候,无法判断左右区间的有序性,故不能对原始数组进行折半,搜索数组的长度只能减少1。

class Solution {
        public boolean search(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int mid = (left+right)/2;

        while (left<=right) {
            mid = (left+right)/2;
            if (nums[mid]==target){
                return true;
            }
            //左边有序
            if (nums[mid]>nums[left]){

                //先在有序区间里找
                //目标值在有序范围内
                if (target<=nums[mid] && target>=nums[left]){
                    return  binSea(nums, left, mid, target)==-1?false:true;
                }

                //有序区间没有再去无序区间找
                left = mid+1;

            }else if (nums[mid]<nums[right]){
                //右边有序
                if (target>=nums[mid]&&target<=nums[right]){
                    return binSea(nums,mid,right,target)==-1?false:true;
                }
                right=mid-1;
            }else {
                //无法判断有序性,不能对数组进行折半操作
                if (nums[left]==nums[mid]){
                    left++;
                }else {
                    right--;
                }
            }
        }
        
        return false;
    }

    public int binSea(int[]nums,int left,int right,int target){
        int mid;
        while (left<=right){
            mid = (left+right)/2;
            if (nums[mid]==target){
                return mid;
            }else if (nums[mid]>target){
                right = mid-1;
            }else {
                left = mid+1;
            }
        }
        return -1;
    }
}

 

以上是关于33. 搜索旋转排序数组的主要内容,如果未能解决你的问题,请参考以下文章

33. 搜索旋转排序数组

33. 搜索旋转排序数组

LeetCode33. 搜索旋转排序数组

Leetcode 33.搜索旋转排序数组

leetcode33 搜索旋转排序数组(Medium)

[leetcode] 33. 搜索旋转排序数组(Java)