题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [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
题解
看到题目要求的复杂度为[latex] o(log_2n) [/latex],首先想到的二分查找法,但一般的适用场景是整体有序,对于这种情况,如果我们能确定旋转位置rotate_idx,则整个序列分成两部分:[0, rotate_idx)和[rotate_idx, nums.size())。当target >= nums[0]时target只可能出现前一部分,反之,则出现后一部分。 如何确定rotate_idx?借鉴官方题解,这里也采用二分法。 [0, rotate_idx)和[rotate_idx, nums.size())有以下特点: [latex] \\begin {split} nums[0] < nums[1] < \\cdots< nums[rotate\\_idx - 1] > \\\\ nums[rotate\\_idx] <\\cdots nums[rotate_idx]即可。 具体二分的方式查看代码。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| class Solution { public: int search(vector<int>& nums, int target) { int beg = 0, end = nums.size() - 1, mid = (beg + end) / 2; int rotate_index = 0; if(nums.size() == 0){ return -1; } while(beg <= end){ mid = (beg + end) / 2; if(mid < nums.size() - 1 && nums[mid] > nums[mid + 1]){ rotate_index = mid + 1; break; } else if(nums[mid] >= nums[beg]){ beg = mid + 1; } else{ end = mid - 1; } } if(target >= nums[0]){ beg = 0, end = (rotate_index == 0?nums.size() - 1:rotate_index - 1); } else{ beg = rotate_index; end = nums.size() - 1; } while(beg <= end){ mid = (beg + end) / 2; if(nums[mid] > target){ end = mid - 1; } else if(nums[mid] < target){ beg = mid + 1; } else{ return mid; } } if(beg > end){ return -1; } else{ return 0; } } };
|
执行结果