【剑指Offer | C++ 】面试题11:旋转数组中最小值(两个部分的指针思路 & 最小值在两个指针之间的思路)

24 篇文章 0 订阅
24 篇文章 0 订阅
文章讲述了如何在已知进行过旋转的非递减排序数组中找到最小元素。通过使用双指针法,分别指向数组的两端,比较并根据中间值调整指针位置,处理了数组中存在相同值的特殊情况。提供了两种不同的代码实现来解决这个问题,一种是当遇到相同值时采用线性搜索,另一种是在判断条件中调整指针位置。
摘要由CSDN通过智能技术生成

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4, 5, 1, 2}是数组{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

思路1:两个部分的指针

  • 普通情况:
    数组可以分为两个递增的部分,使用两个指针分别指向两个部分,
    其中p1不断指向第一部分的最右,p2不断指向第二部分的最左
  • 特殊情况:
    数组中有相同的值,如1,0,1,1,1
    无法移动指针,对此情况只能O(n)便利。

代码:

#include<iostream>
using namespace std;

int RotationMin(int data[], int length) {

    int p1 = 0;
    int p2 = length - 1;
    if (data[p1] < data[p2])
        return data[p1];

    int mid;
    while (data[p1] >= data[p2])
    {
        if (p2 - p1 == 1)
            return data[p2];
        mid = ((p2 - p1) >> 1) + p1;
        if (data[p1] == data[p2] && data[mid] == data[p1]) {
            int minValue = data[p1];
            for (int i = p1; i <= p2;i++) {
                minValue = min(minValue, data[i]);
            }
            return minValue;
        }
        


        if (data[mid] >= data[p1]) {
            p1 = mid;
        }
        else {
            p2 = mid;
        }
    }
    return data[mid];
}

int main()
{
    int a[] = { 4,5,1,2,3};
    cout << RotationMin(a, 5);

}

需要注意的是:p1 = mid;,代表的是p1一直在第一部分的数组
如果是p1 = mid+1;也可以使用下面的写法:

思路2:最小值困在两个指针之间

思路:mid的值比p1大说明最小值肯定在mid+1及其右边,因此可以+1

如果等于p1的值或者小于都有可能在包含mid 的区间内
同理,如果找的是最大值就可以在这个情况下mid-1

  • 代码:
#include<iostream>
using namespace std;

int RotationMin(int data[], int length) {

    int p1 = 0;
    int p2 = length - 1;
    if (data[p1] < data[p2])
        return data[p1];

    int mid = ((p2 - p1) >> 1) + p1;

    while (p2-p1!=1)
    {
        if (data[p1] == data[p2] && data[mid] == data[p1]) {
            int minValue = data[p1];
            for (int i = p1; i <= p2;i++) {
                minValue = min(minValue, data[i]);
            }
            return minValue;
        }

        if (data[mid] > data[p1]) {
            p1 = mid+1;
        }
        else {
            p2 = mid;
        }
        mid = ((p2 - p1) >> 1) + p1;
    }
    return min(data[p1],data[p2]);
}

int main()
{
    int a[] = {3,4,0,1,2};
    cout << RotationMin(a, 5);

}

由于只有两个元素时,mid总是第一个元素,因此直接返回两个的最小值即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赛文X

觉得不错就打赏下呗mua~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值