There is an integer array nums
sorted in ascending order (with distinct values).
Prior to being passed to your function, nums
is rotated at an unknown pivot index k
(0 <= k < nums.length
) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(0-indexed). For example, [0,1,2,4,5,6,7]
might be rotated at pivot index 3
and become [4,5,6,7,0,1,2]
.
Given the array nums
after the rotation and an integer target
, return the index of target
if it is in nums
, or -1
if it is not in nums
.
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0 Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3 Output: -1
Example 3:
Input: nums = [1], target = 0 Output: -1
Constraints:
1 <= nums.length <= 5000
-104 <= nums[i] <= 104
- All values of
nums
are unique. nums
is guaranteed to be rotated at some pivot.-104 <= target <= 104
Follow up: Can you achieve this in O(log n)
time complexity?
在旋转有序数组中搜索。
整数数组 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 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这题grandyang大神的解释我直接搬过来了,非常详细。注意二分找到mid的位置之后,其实左半边和右半边是有可能都是有序的,所以需要额外判断到底是动 start 还是动 end。跳出 while 循环之后,因为 while的条件是 start + 1 < end 所以跟 153,154 题类似,跳出 while 的时候满足 start < end。所以需要再判断 target 是否在 start 或者在 end。
时间O(logn)
空间O(1)
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @param {number} target 4 * @return {number} 5 */ 6 var search = function(nums, target) { 7 // corner case 8 if (nums === null || nums.length === 0) return -1; 9 10 // normal case 11 let start = 0; 12 let end = nums.length - 1; 13 while (start + 1 < end) { 14 let mid = Math.floor(start + (end - start) / 2); 15 if (nums[mid] === target) { 16 return mid; 17 } 18 // if target is on the left side 19 if (nums[start] < nums[mid]) { 20 if (nums[start] <= target && target <= nums[mid]) { 21 end = mid; 22 } else { 23 start = mid; 24 } 25 } 26 // if target is on the right side 27 else { 28 if (nums[mid] <= target && target <= nums[end]) { 29 start = mid; 30 } else { 31 end = mid; 32 } 33 } 34 } 35 if (nums[start] === target) return start; 36 if (nums[end] === target) return end; 37 return -1; 38 };
Java实现一,while (start + 1 < end)
1 class Solution { 2 public int search(int[] nums, int target) { 3 int start = 0; 4 int end = nums.length - 1; 5 // start + 1 < end 6 // 举例,start - 0, end = 3 7 // 中间隔了起码有start + 1和start + 2两个下标 8 // 这样跳出while循环的时候,end < start 9 // 才有了最后的两个特判 10 while (start + 1 < end) { 11 int mid = start + (end - start) / 2; 12 if (nums[mid] == target) { 13 return mid; 14 } 15 // left half is increasing 16 if (nums[start] < nums[mid]) { 17 if (nums[start] <= target && target <= nums[mid]) { 18 end = mid; 19 } else { 20 start = mid; 21 } 22 } 23 // right half is increasing 24 else { 25 if (nums[mid] <= target && target <= nums[end]) { 26 start = mid; 27 } else { 28 end = mid; 29 } 30 } 31 } 32 if (nums[start] == target) { 33 return start; 34 } 35 if (nums[end] == target) { 36 return end; 37 } 38 return -1; 39 } 40 }
Java实现二,while (start <= end)
如果是 <= 则说明二分法的两端是闭区间 [start, end] ;如果写成start + 1 < end,其实是在start和end之间预留了两个空格,在跳出while循环后要额外判断。
1 class Solution { 2 public int search(int[] nums, int target) { 3 int start = 0; 4 int end = nums.length - 1; 5 // start <= end最后跳出while循环的时候end < start 6 // end和start是邻近的两个index,所以无需特判 7 while (start <= end) { 8 int mid = start + (end - start) / 2; 9 if (target == nums[mid]) { 10 return mid; 11 } 12 // 左半段是有序的 13 if (nums[start] <= nums[mid]) { 14 // target 在这段里 15 if (target >= nums[start] && target < nums[mid]) { 16 end = mid - 1; 17 } else { 18 start = mid + 1; 19 } 20 // 右半段是有序的 21 } else { 22 if (target > nums[mid] && target <= nums[end]) { 23 start = mid + 1; 24 } else { 25 end = mid - 1; 26 } 27 } 28 } 29 return -1; 30 } 31 }