33. Search in Rotated Sorted Array
Leetcode
https://leetcode.com/problems/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 possibly rotated at an unknown pivot index k (1 <= 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 possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.
You must write an algorithm with O(log n) runtime complexity.
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1Example 3:
Input: nums = [1], target = 0
Output: -1解答
方法一
先找出整個矩陣最大值的 index (rotateIndex),再看 target 應該是要在 rotateIndex 的左邊或右邊開始找
var search = function(nums, target) {
const getRotateIndex = () => {
let rotateIndex = 0;
let low = 0;
let high = nums.length - 1;
while(low < high) {
const mid = Math.ceil((low+high) / 2);
if(nums[mid] > nums[rotateIndex]) {
rotateIndex = mid;
low = mid;
} else {
high = mid - 1;
}
}
return rotateIndex;
}
// 找出矩陣最大值的 index
const rotateIndex = getRotateIndex();
// 目標值是否該從左邊開始找
const isSearchLeftPart = target >= nums[0];
let [low, high] = isSearchLeftPart ? [0, rotateIndex] : [rotateIndex + 1, nums.length - 1]
// console.log(rotateIndex, low, high)
while(low < high) {
const mid = Math.floor((low+high) / 2);
if(target === nums[mid]) return mid;
if(target < nums[mid]) {
high = mid;
} else {
low = mid + 1;
}
}
// 如果找到最後還是不等於 target 的話,等於不存在 return -1
return nums[low] !== target ? -1 : low;
};Runtime: 109 ms, faster than 14.09% of JavaScript online submissions for Search in Rotated Sorted Array.
Memory Usage: 39.6 MB, less than 83.42% of JavaScript online submissions for Search in Rotated Sorted Array.
方法二
每次 binary search 時都根據 mid 跟 target 及 nums[0] 之間的大小關係,決定怎麼設定下次搜尋的上下限
var search = function(nums, target) {
let low = 0;
let high = nums.length - 1;
if(target === nums[0]) return 0;
while(low < high) {
const mid = Math.floor((low+high) / 2);
if(target === nums[mid]) return mid;
// 代表 mid 的位置是在 nums 矩陣的左邊
if(nums[mid] >= nums[0]) {
// target 在 nums 矩陣的左邊
if(target > nums[0]) {
if(target > nums[mid]) low = mid + 1;
else high = mid;
} else low = mid + 1;
} else {
// target 在 nums 矩陣的左邊,但是 mid 在 nums 矩陣右邊,所以 high 設成 mid
if(target > nums[0]) high = mid;
else {
// target 在 nums 矩陣的右邊,mid 在 nums 矩陣右邊,且 target > nums[mid]
// 所以往右邊找 low 設成 mid + 1
if(target > nums[mid]) low = mid + 1;
else high = mid;
}
}
}
return nums[low] !== target ? -1 : low;
};Runtime: 76 ms, faster than 71.83% of JavaScript online submissions for Search in Rotated Sorted Array.
Memory Usage: 40.1 MB, less than 37.65% of JavaScript online submissions for Search in Rotated Sorted Array.
測資
let nums = [4,5,6,7,0,1,2], target = 0; // 4
// nums = [4,5,6,7,0,1,2], target = 3; // -1
// nums = [1], target = 0; // -1
// nums = [1], target = 1; // 0
// nums = [1, 3], target = 3; // 1
console.log(search(nums, target))Last updated
Was this helpful?