搜索旋转有序数组和处理重复元素的解题思路及代码(二分查找)

介绍:

在解决算法问题中,搜索旋转有序数组以及处理重复元素是两个常见的问题。本篇博文将详细介绍这两个问题的解题思路和代码实现,并解释其中的关键步骤。

目录:

搜索旋转有序数组问题
题目描述
解题思路
示例代码
处理重复元素的搜索旋转有序数组问题
题目描述
解题思路
示例代码

搜索旋转有序数组问题:

题目描述:

假设一个已排序的数组在某个未知的枢轴处发生了旋转(例如,0 1 2 4 5 6 7 可能变为 4 5 6 7 0 1 2)。给定一个目标值进行搜索。如果在数组中找到了目标值,则返回其索引;否则返回 -1。可以假设数组中不存在重复元素。

解题思路:

使用二分查找的思想来解决问题。关键是在每一步中确定搜索范围。通过比较中间元素和起始元素的大小关系,判断旋转点在左侧还是右侧,然后更新搜索范围,直到找到目标值或搜索范围为空。

解决方法:

定义两个指针 left 和 right 分别指向数组的起始位置和结束位置。
使用循环,当 left <= right 时进行迭代。
在每一次迭代中,计算中间元素的索引 mid,并将其与目标值进行比较。
如果中间元素等于目标值,则直接返回 mid。
否则,根据中间元素和起始元素的大小关系,判断旋转点在 left 到 mid 之间还是在 mid+1 到 right 之间。
如果旋转点在 left 到 mid 之间,且目标值位于该范围内,则将 right 更新为 mid-1。
否则,将 left 更新为 mid+1。
如果循环结束时仍然没有找到目标值,说明目标值不存在于数组中,返回 -1。

示例代码:

int searchInRotatedSortedArray(vector<int>& nums, int target) {
    
    
    int left = 0;
    int 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 (target >= nums[left] && target < nums[mid]) {
    
    
                right = mid - 1;
            } else {
    
    
                left = mid + 1;
            }
        } else {
    
    
            if (target > nums[mid] && target <= nums[right]) {
    
    
                left = mid + 1;
            } else {
    
    
                right = mid - 1;
            }
        }
    }

    return -1;
}

处理重复元素的搜索旋转有序数组问题:

题目描述:

假设一个已排序的数组在某个未知的枢轴处发生了旋转(例如,0 1 2 4 5 6 7 可能变为 4 5 6 7 0 1 2)。给定一个目标值进行搜索。如果在数组中找到了目标值,则返回 true;否则返回 false。可以假设数组中存在重复元素。

解题思路:

在处理重复元素的情况下,我们需要处理中间元素等于起始元素的特殊情况,并将起始位置向右移动一位。其他部分与之前的解决方案相似。

如果允许存在重复元素,则会影响运行时复杂度,并且需要修改原有的解决方案。在允许重复元素的情况下,可能会出现以下情况:数组的起始元素、中间元素和结束元素可能是相等的。这会导致无法确定旋转点所在的区间。

解决方法

为了解决这个问题,我们需要对中间元素和起始元素进行比较,并考虑如下三种情况:

如果中间元素大于起始元素,则说明旋转点在右侧,我们可以将起始位置设置为中间位置加1。
如果中间元素小于起始元素,则说明旋转点在左侧,我们可以将结束位置设置为中间位置减1。
如果中间元素等于起始元素,无法确定旋转点所在的区间,可以将起始位置向右移动一位。

示例代码:

bool searchInRotatedSortedArray(vector<int>& nums, int target) {
    
    
    int left = 0;
    int right = nums.size() - 1;

    while (left <= right) {
    
    
        int mid = left + (right - left) / 2;

        if (nums[mid] == target) {
    
    
            return true;
        }

        if (nums[left] == nums[mid]) {
    
    
            left++;
        } else if (nums[left] < nums[mid]) {
    
    
            if (target >= nums[left] && target < nums[mid]) {
    
    
                right = mid - 1;
            } else {
    
    
                left = mid + 1;
            }
        } else {
    
    
            if (target > nums[mid] && target <= nums[right]) {
    
    
                left = mid + 1;
            } else {
    
    
                right = mid - 1;
            }
        }
    }

    return false;
}

结论:

本篇博文详细介绍了搜索旋转有序数组和处理重复元素的解题思路及代码实现。通过运用二分查找的思想,我们可以在旋转有序数组中高效地搜索目标值。同时,在处理重复元素的情况下,需要特别注意中间元素和起始元素的比较。希望本文能帮助读者理解和解决这两个问题,并在实际编程中灵活运用。如果您想深入了解更多细节,请参阅相关的算法书籍和资料。祝您在算法问题上取得成功!

猜你喜欢

转载自blog.csdn.net/qq_46017342/article/details/131744980
今日推荐