IT评测·应用市场-qidao123.com
标题:
力扣第三十三题——搜索旋转排序数组
[打印本页]
作者:
张春
时间:
2024-7-30 23:24
标题:
力扣第三十三题——搜索旋转排序数组
内容介绍
整数数组 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:
<strong>输入:</strong>nums = [4,5,6,7,0,1,2], target = 0
<strong>输出:</strong>4
复制代码
示例 2:
<strong>输入:</strong>nums = [4,5,6,7,0,1,2], target = 3
<strong>输出:</strong>-1
复制代码
示例 3:
<strong>输入:</strong>nums = [1], target = 0
<strong>输出:</strong>-1
复制代码
提示:
1 <= nums.length <= 5000
-104 <= nums
<= 104
nums 中的每个值都
独一无二
标题数据保证 nums 在预先未知的某个下标上进行了旋转
-104 <= target <= 104
完整代码
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return -1;
}
if (n == 1) {
return nums[0] == target ? 0 : -1;
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid]) {
r = mid - 1;
} else {
l = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return -1;
}
}
复制代码
思绪详解
方法概述
search方法实现了一个改进的二分查找算法,适用于经过旋转的有序数组。旋转数组的特点是,数组的一部门是有序的,另一部门也是有序的,但是两部门之间的次序被打乱了。
思绪详解
边界情况处理
:
假如数组长度为0,直接返回-1,因为没有元素可以查找。
假如数组长度为1,查抄该元素是否为目标值,假如是则返回索引0,否则返回-1。
初始化二分查找的左右指针
:
l(左指针)初始化为0。
r(右指针)初始化为数组长度减1。
二分查找循环
:
当l小于等于r时,进行以下操纵:
计算中央位置mid。
假如nums[mid]等于目标值target,直接返回mid。
判定中央位置的元素与数组首元素的关系
:
假如nums[0]小于等于nums[mid],说明左半部门是有序的:
假如目标值target在nums[0]和nums[mid]之间,则将右指针r移动到mid - 1。
否则,将左指针l移动到mid + 1。
假如nums[0]大于nums[mid],说明右半部门是有序的:
假如目标值target在nums[mid]和nums[n - 1]之间,则将左指针l移动到mid + 1。
否则,将右指针r移动到mid - 1。
循环竣事
:
假如循环竣事还没有找到目标值,说明目标值不在数组中,返回-1。
代码解释
以下是代码中关键步骤的解释:
public int search(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return -1; // 数组为空,直接返回-1
}
if (n == 1) {
return nums[0] == target ? 0 : -1; // 数组只有一个元素,检查是否为目标值
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2; // 计算中间位置
if (nums[mid] == target) {
return mid; // 找到目标值,返回索引
}
if (nums[0] <= nums[mid]) {
// 左半部分有序
if (nums[0] <= target && target < nums[mid]) {
r = mid - 1; // 目标值在左半部分
} else {
l = mid + 1; // 目标值在右半部分
}
} else {
// 右半部分有序
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1; // 目标值在右半部分
} else {
r = mid - 1; // 目标值在左半部分
}
}
}
return -1; // 未找到目标值,返回-1
}
复制代码
知识点精粹
二分查找算法(Binary Search)
基本概念
:一种在有序数组中查找特定元素的搜索算法,通过不断将搜索区间减半来提高搜索效率。
时间复杂度
:O(log n),此中n是数组的长度。
2. 循环数组的处理
旋转数组
:一个有序数组在某些点上被旋转,使得数组的一部门有序,另一部门同样有序,但整体不再有序。
二分查找的适应
:通过比较中央元素与数组首元素,确定哪部门是有序的,从而决定搜索方向。
3. 边界条件处理
空数组
:假如数组为空,直接返回-1,因为没有元素可以查找。
单位素数组
:假如数组只有一个元素,直接比较该元素与目标值。
4. 循环与递归的选择
循环实现
:利用while循环进行二分查找,避免了递归大概带来的额外开销。
5. 中央位置的取值
防止溢出
:利用(l + r) / 2计算中央位置,而非(l + r) >> 1,虽然后者在位运算上更高效,但在此场景下避免了整型溢出的风险。
6. 搜索区间的调整
左半部门有序
:假如中央元素大于等于首元素,说明左半部门是有序的,根据目标值的位置调整搜索区间。
右半部门有序
:假如中央元素小于首元素,说明右半部门是有序的,同样根据目标值的位置调整搜索区间。
7. 返回效果
找到目标值
:假如中央元素等于目标值,返回中央位置的索引。
未找到目标值
:假如循环竣事仍未找到目标值,返回-1。
8. 算法优化
避免重复比较
:在每次循环中,仅比较一次中央元素与目标值,减少了不须要的比较次数。
通过以上知识点,我们可以看到,虽然代码实现的是二分查找,但针对旋转数组的特性进行了适当的调整,使得算法能够适应这种特别的有序数组。这些知识点对于明白和实现高效的搜索算法至关重要。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4