leetcode33.搜索旋转排序数组

Posted by serrini on March 6, 2020

leetcode33.搜索旋转排序数组

Question

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [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], target = 3 输出: -1

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Answer

package pid33;

public class Solution {

	public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        int pivot;
        while (left <= right) {
            pivot = left + (right - left) / 2;
            if (nums[pivot] == target) {
                return pivot;           
            }
            
            //左半边升序
            if (nums[left] <= nums[pivot]) {
            	if(target >= nums[left] && target < nums[pivot]) {
            		right = pivot - 1;
            	}else {
            		left = pivot + 1;
            	}
            }else {
            	if(target > nums[pivot] && target <= nums[right]) {
            		left = pivot + 1;
            	}else {
            		right = pivot - 1;
            	}
            }
        }
        return -1;
	}
}

Attention

官方解法思路:

  • 二分法找到数组中最小的元素,并记录下该处rotation index
  • 比较target与第一个数组元素的大小
    • 如果target>nums[0],则在rotation index的左边查找
    • 如果taeget<nums[0],则在rotation index的右边查找
  • 查找过程用二分法

另一解法:

  • 首先数字无重复
  • nums[left]与nums[pivot]比较由此可分成两类情况
    • 一类是nums[left]<=nums[pivot],即前半部分有序,如2 3 4 5 6 7 1,在这种情况下如果target在左边就到左边去找,如果target在右边则修改left到右边去找
    • 一类是nums[left]>nums[pivot],即后半部分有序,如6 7 1 2 3 4 5,即6>2。此时如果target在升序部分就去右边去找,如果不是就修改right到左边去找
  • 技巧是找出升序的部分,如果是左边升序的情况,判断条件target>=nums[left] && target < nums[pivot]取反之后是target<nums[left] || target >= nums[pivot],就会去右边找,右边升序的情况同理。