LeetCode精选TOP面试题033.搜索旋转排序数组

题目描述

整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给定 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

example
input  : nums = {4,5,6,7,0,1,2}, target = 0
output : 4
input  : nums = {4,5,6,7,0,1,2}, target = 3
output : -1
input  : nums = {3,1}, target = 1
output : 1
input  : nums = {1}, target = 0
output : -1

解题思路

思路 二分查找

  • 先找到数组旋转后的分界线,即前后两个有序数组的分界线
  • 根据 target 的大小,决定在左侧有序数组还是右侧有序数组进行二分查找
  • 执行二分查找确定目标位置

代码(Java)

代码

public class Solution {
    public int search(int[] nums, int target) {
        int div = 0;
        for (int i = 0; i < nums.length - 1; i++) {
            if (nums[i] > nums[i + 1]) {
                div = i;
                break;
            }
        }
        // System.out.println(div);
        // 二分查找
        int left, right;
        int length = nums.length;
        if (nums[div] >= target && nums[0] <= target) {
            left = 0;
            right = div;
        } else if (nums[length - 1] >= target) {
            left = div + 1;
            right = length - 1;
        } else {
            return -1;
        }
        // System.out.println(left + "," + right);
        while (left <= right) {
            // 防止溢出,通常可写作 middle = (right + left) / 2
            int middle = (right - left) / 2 + left;
            if (target == nums[middle] && left <= right) {
                return middle;
            }
            if (target > nums[middle] && left <= right) {
                left = middle + 1;
            } else if (target < nums[middle] && left <= right) {
                right = middle - 1;
            }
        }
        return -1;
    }
}
上一篇:Java -数组 算法


下一篇:【Semantic框架学习日志】(7)segment的使用