[LeetCode] 33. Search in Rotated Sorted Array
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 }