二分搜索对于没排序的数组_搜索旋转排序数组 (二分法+简洁易懂)

题目描述

给你一个整数数组 nums ,和一个整数 target 。
该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4

示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1

示例 3:
输入:nums = [1], target = 0
输出:-1

提示:
    1 <= nums.length <= 5000
    -10^4 <= nums[i] <= 10^4
    nums 中的每个值都 独一无二
    nums 肯定会在某个点上旋转
    -10^4 <= target <= 10^4

解题思路

首先就是暴力求解法:顺序遍历数组,比较每个元素,时间复杂度为O(N)。

如果要在时间复杂度为O(logN)的条件下解决该题,则需要用到二分法查找,首先给出二分法代码模板:

int binarySearch(const vector<int>& nums,int target) {
	int left=0,right=nums.size()-1;
	while(left <= right) {
	    int mid = left + (right - left)/2;
	    if(nums[mid] == target) return mid;
	    else if(nums[mid] < target) left = ++mid;
	    else right = --mid;
	}
	return -1;
}

解题步骤
一般情况下,二分法存在left,right,mid位,来辅助判断。因此,二分法解决该题的步骤如下:

  1. 如果target 在[mid+1,right]序列中,则left = mid+1,否则 right = mid;
  2. 关键是如何判断 target在[mid+1,right]序列中,具体判断如下:
    当[0, mid] 序列是升序: nums[0] <= nums[mid], 当target > nums[mid] || target < nums[0] ,则向后规约;
    当[0, mid] 序列存在旋转位: nums[0] > nums[mid],当target < nums[0] && target > nums[mid],则向后规约;
    当然其它情况就是向前规约了;
  3. 循环判断,直到排除到只剩最后一个元素时,退出循环,如果该元素和 target 相同,直接返回下标,否则返回 -1。

根据解题思路套用二分法模板,具体代码实现如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int L=0,R=nums.size()-1;
        while(L<R) {
            int mid = L + (R-L)/2;
            if( nums[0] <= nums[mid] && ( target > nums[mid] || target < nums[0]))
                L = ++mid;
            else if( target > nums[mid] && target < nums[0])
                L = ++mid;
            else
                R = mid;
        }
        return L==R && nums[L]==target ? L : -1;
    }
};

AC结果

f94b8c66216103600a522d6b72b6aece.png

利用异或对判断条件语句进行简化,简化后的写法如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int L=0,R=nums.size()-1;
        while(L<R) {
            int mid = L + (R-L)/2;
            if((nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]))
                L = ++mid;
            else 
                R = mid;
        }
        return L==R && nums[L]==target ? L : -1;
    }
};

AC结果

053021ec72724f5ff1c54855b57bd348.png

复杂度分析:

  1. 时间复杂度:二分查找,时间复杂度为O(logN);
  2. 空间复杂度:空间复杂度为O(1)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值