题目描述
整数数组 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 。
你必须设计一个时间复杂度为 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
示例 3: 输入:nums = [1], target = 0 输出:-1
提示: 1 <= nums.length <= 5000 -10^4 <= nums[i] <= 10^4 nums 中的每个值都 独一无二 题目数据保证 nums 在预先未知的某个下标上进行了旋转 -10^4 <= target <= 10^4
题解
解题思路
思路一(二分查找):
- 因数组是通过旋转得到,所以存在两个升序部分(也可能只存在一个)。我们采用二分查找的方法,查找到 mid 中间坐标,此时 mid 左右两侧必定是一侧有序,一侧无序(左侧包含 mid,右侧区间包含 mid)(有序也可看做无序处理)。
- 首先判断 nums[mid] 是否等于 target,若相等则直接返回。
- 若 nums[mid] != target。可通过 nums[mid] 与 nums[left] 的比较,来判断左侧区域是否有序。
- nums[mid] >= nums[left](注意这里是>=,当存在两个元素时 left = mid。如 [1,2],target=2)左侧有序,右侧无序,则需判断 target 是否在 nums[left]~nums[mid] 的区间内。
- 若 target 在区间内,则在左区间(有序区间)继续进行查找(此时为普通的二分查找):right = mid-1
- 若 target 不在区间内,则在右区间(无序区间)继续进行查找:left = mid+1
- nums[mid] <= nums[right] 左侧无序,右侧有序,则需判断 target 是否在 nums[mid]~nums[right] 的区间内。
- 若 target 在区间内,则在右区间(有序区间)继续进行查找(此时为普通的二分查找):left = mid+1
- 若 target 不在区间内,则在左区间(无序区间)继续进行查找:right = mid-1
- nums[mid] >= nums[left](注意这里是>=,当存在两个元素时 left = mid。如 [1,2],target=2)左侧有序,右侧无序,则需判断 target 是否在 nums[left]~nums[mid] 的区间内。
- 若 left > right 则查找失败。
例:nums={4,5,6,7,0,1,2};target=0; 初始:left = 0, right = 6, target = 0,中间元素 nums[mid] = 7,不等于目标值,左侧有序,target 不在左侧区间,更新 left = 4。 第二次:left = 4, right = 6,中间元素 nums[mid] = 1,不等于目标值,左侧有序,target 在左侧区间,更新 right = 4。 第三次:left = 4, right = 4,中间元素 nums[mid] = 0,等于目标值,返回索引 4。
- 复杂度分析:
- 时间复杂度:O(logn),其中 n 为 nums 数组的大小。整个算法时间复杂度即为二分查找的时间复杂度 O(logn)。
- 空间复杂度:O(1)。
代码实现
代码实现(思路一(二分查找)):
{
:
{
left = , right = nums.() - ;
mid;
(left <= right) {
mid = left + (right - left) / ;
(nums[mid] == target) mid;
(nums[left] <= nums[mid]) {
(nums[left] <= target && target < nums[mid]) {
right = mid - ;
} {
left = mid + ;
}
} {
(nums[mid] < target && target <= nums[right]) {
left = mid + ;
} {
right = mid - ;
}
}
}
;
}
};


