题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1
。你可以假设数组中不存在重复的元素。你的算法时间复杂度必须是 O(log n)
级别。
分析
该题有两个关键点:
- 如何理解旋转:题中的旋转是在一个点旋转,所以对于数组如
[1,2,3]
,不存在类似这样的旋转结果:[3,2,1]
- 要求时间复杂度为
O(logn)
,很容易想到应该用二分法,但关键在于如何讨论出所有可能情况。
解题思路
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
| class Solution { public int search(int[] nums, int target) { int len = nums.length; int left = 0; int right = len-1; if(len == 0) return -1; int mid; while(left<=right){ mid = (left+right)>>1; if(nums[mid]==target) return mid; else if(nums[left]<=nums[mid]&&nums[mid]<=nums[right]){ if(target>nums[mid]) left = mid + 1; else right = mid - 1; } else if(nums[left]<=nums[mid]&&nums[mid]>=nums[right]){ if(target>nums[mid]) left = mid + 1; else if(target<nums[mid]&&target<nums[left]) left = mid + 1; else right = mid - 1; } else if(nums[left]>=nums[mid]&&nums[mid]<=nums[right]){ if(target<nums[mid]) right = mid - 1; else if(target>nums[mid]&&target>nums[right]) right = mid - 1; else left = mid + 1; } } return -1; } }
|
最后
不得不说位运算是个神器,时间消耗只有传统乘除法的1/4
,同时位运算也是实现乘除法的一种办法。