Suppose a sorted array is rotated at some pivot unknown to you beforehand.數組
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).優化
You are given a target value to search. If found in the array return its index, otherwise return -1.spa
You may assume no duplicate exists in the array.code
解法1:順序查找,時間複雜度O(n)。blog
class Solution { public: int search(vector<int>& nums, int target) { int n = nums.size(), i = 0; while(i < n && target != nums[i]) i++; return i == n ? -1 : i; } };
解法2:旋轉數組是分爲兩個有序數組,所以能夠使用二分查找。若數組首元素小於數組尾元素,則數組沒有旋轉,直接使用二分查找binarySearch便可;不然(1)初始化left=0,right=n-1,取mid=(left+right)/2;(2)若是target==nums[mid],則直接返回mid;不然若nums[left]<nums[mid],說明nums[left, ..., mid-1]是有序的,而nums[mid+1, ... , n-1]是旋轉的,對前者調用binarySearch,若沒找到再對後者調用search;若nums[left]>nums[mid],說明nums[left, ..., mid-1]是旋轉的,而nums[mid+1, ... , n-1]是有序的,對後者調用binarySearch,若沒找到再對前者調用search。get
class Solution { public: int search(vector<int>& nums, int target) { int n = nums.size(); if (n < 2) return n == 1 ? (target == nums[0] ? 0 : -1) : -1; int res, left = 0, right = n - 1; if (nums[left] < nums[right]) res = binarySearch(nums, left, right, target); else { int mid = (left + right) >> 1; if (target == nums[mid]) res = mid; else if (nums[left] < nums[mid]) { if ((res = binarySearch(nums, left, mid - 1, target)) == -1) { vector<int> tmp(nums.begin() + mid + 1, nums.end()); res = search(tmp, target); res = res == -1 ? -1 : res + mid + 1; } } else { if ((res = binarySearch(nums, mid + 1, right, target)) == -1) { vector<int> tmp(nums.begin(), nums.begin() + mid); res = search(tmp, target); } } } return res; } private: int binarySearch(vector<int>& nums, int left, int right, int key) { if (left > right) return -1; int mid = (left + right) >> 1; if (key == nums[mid]) return mid; else if (key > nums[mid]) return binarySearch(nums, mid + 1, right, key); else return binarySearch(nums, left, mid - 1, key); } };
上面的代碼能夠進一步優化。首先根據nums[mid]和nums[right]的關係能夠肯定數組的哪部分是有序的:若是中間的數小於最右邊的數,則右半段是有序的,若中間數大於最右邊數,則左半段是有序的。而後再根據有序部分首尾兩個數字和target的大小關係來判斷target存在於哪一部分。it
class Solution { public: int search(vector<int>& nums, int target) { int n = nums.size(); int res = -1, left = 0, right = n - 1; while(left <= right) { int mid = (left + right) >> 1; if(target == nums[mid]) { res = mid; break; } else if(nums[mid] < nums[right]) //後半部分有序 { if(target > nums[mid] && target <= nums[right]) left = mid + 1; else right = mid - 1; } else //前半部分有序 { if(target >= nums[left] && target < nums[mid]) right = mid - 1; else left = mid + 1; } } return res; } };
或者nums[mid]和nums[left]比較也能夠,可是要注意mid=left的狀況得單獨拿出來討論io
class Solution { public: int search(vector<int>& nums, int target) { int n = nums.size(); int res = -1, left = 0, right = n - 1; while(left <= right) { int mid = ((left + right) >> 1); if(target == nums[mid]) { res = mid; break; } else if(nums[mid] > nums[left]) //前半部分有序 { if(target >= nums[left] && target < nums[mid]) right = mid - 1; else left = mid + 1; } else if(nums[mid] < nums[left]) //後半部分有序 { if(target > nums[mid] && target <= nums[right]) left = mid + 1; else right = mid - 1; } else //nums[mid]==nums[left]的狀況,包括mid=left和存在重複值兩種狀況 left++; } return res; } };