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;
    }
}

原文地址:https://www.cnblogs.com/AshOfTime/p/10798237.html

时间: 2024-10-09 16:34:57

33. 搜索旋转排序数组的相关文章

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

33. 搜索旋转排序数组 说实话这题我连题都没有看懂....真是醉了 二分,没意思,直接交了- - https://www.jiuzhang.com/solutions/search-in-rotated-sorted-array/#tag-other 原文地址:https://www.cnblogs.com/acbingo/p/9302337.html

[LeetCode] 33. 搜索旋转排序数组 ☆☆☆(二分查找)

描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 . 你可以假设数组中不存在重复的元素. 你的算法时间复杂度必须是 O(log n) 级别. 示例 1: 输入: nums = [4,5,6,7,0,1,2], target = 0输出: 4示例 2: 输入: nums = [4,5,6,7,0,1,2], ta

[LeetCode]33. 搜索旋转排序数组(二分)

题目 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组?[0,1,2,4,5,6,7]?可能变为?[4,5,6,7,0,1,2]?). 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回?-1?. 你可以假设数组中不存在重复的元素. 你的算法时间复杂度必须是?O(log?n) 级别 题解 由最原始的二分框架来做. 如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在

LeetCode 33. 搜索旋转排序数组(C#实现)——二分查找

问题:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/submissions/ 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 . 你可以假设数组中不存在重复的元素. 你的算法时间复杂度必须是 O(log n) 级别. 示例 1: 输入

Leetcode 33. 搜索旋转排序数组

class Solution { public: int search(vector<int>& nums, int target) { int beg = 0; int end = nums.size()-1; while(beg <= end) { int mid = beg + (end-beg)/2; //找到就直接返回 if(target == nums[mid]) return mid; else if( target < nums[mid]) { if(num

LeetCode 81——搜索旋转排序数组 II

1. 题目 2. 解答 2.1. 方法一 基于 LeetCode 33--搜索旋转排序数组 中的方法二. 当 nums[mid] = nums[right] 时,比如 [1, 1, 2, 1, 1],[1, 1, 0, 1, 1],为了找到正确的转折点,我们查看 [mid, right] 之间有没有不等于 nums[mid] 的值,若有,则继续向右查找:否则向左查找. class Solution { public: int Binary_Search(vector<int>& num

63. 搜索旋转排序数组 II

跟进"搜索旋转排序数组",假如有重复元素又将如何? 是否会影响运行时间复杂度? 如何影响? 为何会影响? 写出一个函数判断给定的目标值是否出现在数组中. 样例 给出[3,4,4,5,7,0,1,2]和target=4,返回 true 发现lintcode有一点不好就是这种O(n)的解法也能给过 1 bool search(vector<int> &A, int target) { 2 // write your code here 3 vector<int&g

LeetCode(力扣)——Search in Rotated Sorted Array 搜索旋转排序数组 python实现

题目描述: python实现 Search in Rotated Sorted Array 搜索旋转排序数组   中文:假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 . 你可以假设数组中不存在重复的元素. 你的算法时间复杂度必须是 O(log n) 级别. 英文:Suppose an array sorted i

【leetcode 33】搜索旋转排序数组(第二遍)

题目链接 [题解] 如果没有旋转这么一说. 那么问题就是一道普通的二分查找的题目. 加上旋转之后.也没有让这个题变难多少. 问题的关键在于. 在二分查找的时候. 能够想到用nums[0]这个元素来确定当前二分枚举到的元素是在哪一个区间里面的. 即是在左边那个上升区间里面,还是在右边那个上升区间里面. 不过. 知道在哪个区间以后 还有一个问题. 就是我们不能单纯的就在那个区间里面做二分. 因为那个元素可能是在另外一个区间里的. 所以还得拿目标元素和nums[0]做一个对比. 比它小然后nums[m