旋转数组的最小数字(二分)

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组 {3,4,5,1,2} 为 {1,2,3,4,5} 的一个旋转,该数组的最小值为1。

分析:

1, 2, 3, 4, 5 的一个旋转是 3, 4, 5, 1, 2,通过二分,5 与 3 、 5 与 2 比较,可以得出右边的子数组必定无序,故最小值一定在右边。

1, 2, 3, 4, 5 的另一个旋转是  5, 1, 2, 3, 4,用过二分,2 与 5 、 2 与 4比较,可以得出左边的子数组必定无序,故最小值一定在左边。

多尝试几个例子发现,最大值和最小值一定总在一起(本质因为数组的旋转),而这个导致了左右子数组的无序。

注:1, 1, 1, 0, 1 是特殊的例子,它的中间值与左右边界都相等,此时无法判断,但可以截取这段数组暴力地线性查找。

复制代码
/*
 * 旋转数组的最小数字 
 */
int baoli(vector<int> arr, int a, int b)
{
    int ans = INF;
    for (int i = a; i <= b; i++)
    {
        if (ans > arr[i])
            ans = arr[i];
    }
    return ans;
}
int minNumberInRotateArray(vector<int> rotateArray)
{
    int left = 0, mid = 0;
    int right = rotateArray.size() - 1;
    while (left + 1 < right) {
         // 若边界不等,则二分(说明无序)
        mid = (left + right) >> 1;
        if (rotateArray[mid] < rotateArray[left]) {
            right = mid;
        }
        else if (rotateArray[mid] > rotateArray[right]) {
            left = mid;
        } // 若边界相等,暴力查找
        else {
            return baoli(rotateArray, left, right);
        }
    }
    return rotateArray[right];
}
int main()
{
    vector<int> rotateArray = {1, 1, 1, 0, 1};
    cout << minNumberInRotateArray(rotateArray) << endl;
    return 0;
}
复制代码

从上面的代码可以看出有三条分支,分别是左子数组无序、右子数组无序、无法判断而线性查找三种情况。

注意循环的出口,此题中只剩下两个数时就能判断,此时需要直接跳出,否则程序会无限循环。

posted on   Black_x  阅读(155)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示