欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > LeetCode 算法:搜索旋转排序数组 c++

LeetCode 算法:搜索旋转排序数组 c++

2025/2/22 16:44:59 来源:https://blog.csdn.net/yanceyxin/article/details/140834310  浏览:    关键词:LeetCode 算法:搜索旋转排序数组 c++

原题链接🔗:搜索旋转排序数组
难度:中等⭐️⭐️

题目

整数数组 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
  • -104 <= nums[i] <= 104
  • nums 中的每个值都 独一无二
  • 题目数据保证 nums 在预先未知的某个下标上进行了旋转
  • -104 <= target <= 104

二分查找

  1. 二分查找(Binary Search),也称为折半搜索,是一种在有序数组中查找特定元素的搜索算法。其基本思想是将目标值与数组中间的元素进行比较:

    1. 如果目标值等于中间元素,搜索成功,返回该位置。
    2. 如果目标值小于中间元素,搜索范围缩小至数组的左半部分。
    3. 如果目标值大于中间元素,搜索范围缩小至数组的右半部分。
    4. 这个过程将不断重复,直到找到目标值或者搜索范围为空为止。
  2. 以下是二分查找算法的一般步骤:

    1. 初始化:设置两个指针,一个指向数组的起始位置(通常记为 left),另一个指向数组的结束位置(通常记为 right)。

    2. 循环条件:当 left 小于等于 right 时,继续循环。

    3. 计算中间位置:计算 leftright 之间的中间位置 mid,通常使用 (left + right) / 2

    4. 比较与调整

      • 如果 nums[mid] 等于目标值,根据需要返回 mid 或继续搜索以找到更精确的位置。
      • 如果 nums[mid] 大于目标值,将 right 调整为 mid - 1
      • 如果 nums[mid] 小于目标值,将 left 调整为 mid + 1
    5. 循环结束:如果 left 大于 right,则表示目标值不在数组中,返回一个特定的值(通常是 -1)表示未找到。

  3. 二分查找的效率非常高,时间复杂度为 O(log n),其中 n 是数组的长度。然而,它要求数组是有序的,并且只能应用于一维有序数组。

  4. 下面是一个简单的 C++ 实现示例:

int binarySearch(const std::vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left <= right) {int mid = left + (right - left) / 2; // 防止溢出if (nums[mid] == target) {return mid; // 找到目标值} else if (nums[mid] < target) {left = mid + 1; // 搜索右半部分} else {right = mid - 1; // 搜索左半部分}}return -1; // 未找到目标值
}

这个函数会返回目标值在数组中的索引,如果目标值不在数组中,则返回 -1。

题解

  1. 解题思路:
  • 确定二分查找的可行性:由于数组是局部有序的,我们可以使用二分查找算法来减少搜索范围。

  • 确定中间元素和边界元素的比较:在二分查找的过程中,我们需要比较中间元素与边界元素,以确定应该在左半部分还是右半部分继续搜索。

  • 处理旋转点:由于数组被旋转,我们需要找到旋转点,即数组中第一个大于或等于中间元素的索引。

  • 二分查找逻辑:

    • 如果中间元素等于目标值,返回中间索引。
    • 如果左边界元素小于或等于中间元素(即左边是有序的),比较目标值与左边界和中间元素:
      • 如果目标值在左边界和中间元素之间,搜索左半部分。
      • 否则,搜索右半部分。
    • 否则(即右边是有序的),比较目标值与中间元素和右边界:
      • 如果目标值在中间元素和右边界之间,搜索右半部分。
      • 否则,搜索左半部分。
  • 更新搜索范围:根据上述逻辑,更新左右边界,继续二分查找,直到找到目标值或搜索范围无效。

  • 返回结果:如果找到目标值,返回其索引;否则,返回-1。

  1. c++ demo:
#include <iostream>
#include <vector>// 函数声明
int search(const std::vector<int>& nums, int target);int main() {// 测试用例std::vector<int> nums1 = { 4, 5, 6, 7, 0, 1, 2 };int target1 = 0;std::cout << "Test 1 - Expected: 4, Found: " << search(nums1, target1) << std::endl;std::vector<int> nums2 = { 4, 5, 6, 7, 0, 1, 2 };int target2 = 3; // 注意,这里的目标值不在数组中std::cout << "Test 2 - Expected: -1, Found: " << search(nums2, target2) << std::endl;return 0;
}// 函数定义
int search(const std::vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid;}// 判断左侧是否有序if (nums[left] <= nums[mid]) {if (nums[left] <= target && target < nums[mid]) {right = mid - 1;}else {left = mid + 1;}}else { // 右侧有序if (nums[mid] < target && target <= nums[right]) {left = mid + 1;}else {right = mid - 1;}}}return -1; // 如果没有找到目标值,返回-1
}
  • 输出结果:

Test 1 - Expected: 4, Found: 4
Test 2 - Expected: -1, Found: -1

  1. 代码仓库地址:search

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词