【LeetCode - 33】搜索旋转排序数组

1、题目描述

在这里插入图片描述

2、解题思路

  输入的数组是一个升序排序数组的旋转,可以看成如下图所示的状态:
在这里插入图片描述
  把上图两部分称为:旋转数组左侧和旋转数组右侧。可以分析出一个特点:旋转数组的左侧任意一个元素的值都大于等于右侧元素,使用二分法时,通过比较中间元素与最左侧元素的大小可以直接判断中间元素在旋转数组的左侧还是右侧。

  如果对于每一次调整区间范围,都有以下两种情况:

  1、mid 在左侧部分
在这里插入图片描述

  此时,参照对象就是 nums[0],如果目标值大于等于它,且目标值小于 nums[mid],则 r = mid - 1,否则 l = mid + 1。

  2、mid 在右侧部分
在这里插入图片描述

  此时,参照对象是 nums[n-1] ,如果目标值小于等于它,且目标值大于 nums[mid],则 l = mid + 1,否则 r = mid + 1。

3、解题代码

// Java实现
class Solution {
   public int search(int[] nums, int target) {
        int n = nums.length;    // 获取数组元素个数

        // 空数组
        if (n == 0) {
            return -1;
        }

        // 单元素数组
        if (n == 1) {
            return nums[0] == target ? 0 : -1;
        }

        // 多元素数组
        int left = 0, right = n - 1;    // 初始化待搜索范围的左右边界
        while (left <= right) { // 边界合理性判断
            int mid = left + (right - left) / 2;    // 待搜索范围的中间元素坐标
            if (nums[mid] == target) {  // 找到目标值,返回坐标
                return mid;
            }
            if (nums[0] <= nums[mid]) { // mid在旋转数组的左侧
                if (nums[0] <= target && target < nums[mid]) {
                    right = mid - 1;    // 待搜索范围的右边界更新为 mid-1,不更新为 mid 的原因在于: mid 所在坐标的值在上面就确定不等于目标值
                } else {
                    left = mid + 1; // 待搜索范围的左边界更新为 mid+1
                }
            } else {    // mid在旋转数组的右侧
                if (nums[mid] < target && target <= nums[n - 1]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;  // 遍历完毕,未找到目标
    }
}
// C实现
#include<stdio.h>
#include<stdlib.h>

int search(int *nums, int numsSize, int target){
	// 空数组的情况
	if(numsSize == 0) return -1;

	// 单元素数组的情况
	if(numsSize == 1) return nums[0] == target ? 0 : -1;

	// 多元素数组的情况
	int left = 0, right = numsSize - 1;
	int mid = 0;
	while(left <= right)
	{
		mid = left + (right - left) / 2;
		if(nums[mid] == target) return mid;
		if(nums[0] < nums[mid])	// mid 在左侧数组
		{
			// 注意边界要小于等于
			if(nums[0] <= target && target < nums[mid])
			{
				right = mid - 1;
			}
			else
			{
				left = mid + 1;
			}
		}
		else // mid 在右侧数组
		{
			// 注意边界要小于等于
			if(nums[mid] < target && target <= nums[numsSize-1])
			{
				left = mid + 1;
			}
			else
			{
				right = mid - 1;
			}
		}
	}

	// 找不到
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值