返回

旋转排序数组中的二分查找

后端

在现实生活中,我们经常会遇到有序的数据,例如字典中的单词、电话簿中的姓名、计算机文件系统中的文件等。有序数据的一个常见操作就是查找,即给定一个值,找到它在有序数据中的位置。对于有序数据,我们可以使用二分查找算法来快速找到指定值的位置。

二分查找算法是一种非常高效的查找算法,它通过将查找范围对半分,然后在较小的范围内继续查找,不断缩小查找范围,从而快速找到指定值。但是,如果我们处理的是一个旋转排序数组,传统的二分查找算法将失效。

旋转排序数组是指一个原本有序的数组经过一定次数的旋转操作后形成的数组。旋转操作是指将数组的一部分元素移动到数组的另一部分。例如,将数组[1, 2, 3, 4, 5, 6, 7]旋转一次后,得到[7, 1, 2, 3, 4, 5, 6]。

对于旋转排序数组,传统二分查找算法失效的原因在于,数组不再是单调递增或递减的,因此无法直接使用二分法将查找范围对半分。为了解决这个问题,我们需要对二分查找算法进行修改,使其能够处理旋转排序数组。

修改后的二分查找算法如下:

  1. 初始化两个指针left和right,分别指向数组的左右边界。
  2. 如果left大于right,则表示未找到指定值,返回-1。
  3. 计算中间位置mid = (left + right) / 2。
  4. 如果nums[mid]等于指定值,则返回mid。
  5. 如果nums[left]小于或等于nums[mid],说明数组的左侧是单调递增的。
  6. 如果指定值大于nums[mid],则将left指针移动到mid + 1。
  7. 如果指定值小于或等于nums[mid],则将right指针移动到mid - 1。
  8. 跳转到步骤2。

让我们以一个示例来演示修改后的二分查找算法:

数组: [4, 5, 6, 7, 0, 1, 2]
目标值: 0
  1. 初始化left和right指针,指向数组的左右边界:left = 0,right = 6。
  2. left不大于right,因此继续执行下一步。
  3. 计算mid = (0 + 6) / 2 = 3。
  4. nums[mid] = 7不等于目标值0,因此继续执行下一步。
  5. nums[left] = 4小于nums[mid] = 7,因此数组的左侧是单调递增的。
  6. 因为目标值0小于nums[mid] = 7,所以将right指针移动到mid - 1,即right = 2。
  7. 跳转到步骤2。

现在,left = 0,right = 2。

  1. 初始化left和right指针,指向数组的左右边界:left = 0,right = 2。
  2. left不大于right,因此继续执行下一步。
  3. 计算mid = (0 + 2) / 2 = 1。
  4. nums[mid] = 5不等于目标值0,因此继续执行下一步。
  5. nums[left] = 4小于nums[mid] = 5,因此数组的左侧是单调递增的。
  6. 因为目标值0小于nums[mid] = 5,所以将right指针移动到mid - 1,即right = 0。
  7. 跳转到步骤2。

现在,left = 0,right = 0。

  1. left大于right,表示未找到指定值,返回-1。

因此,在旋转排序数组[4, 5, 6, 7, 0, 1, 2]中找不到目标值0。