输出一个为递增排序数组的旋转数组中的最小元素——8

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

    当然了,将数组遍历一遍肯定能找出最小值,但其时间复杂度为O(N),效率是最低的,因此,应该有一种更高效的解决办法。

    

    因为原数组是递增的,因此数组的第一个元素一定是最小值,而旋转之后,其最小值就会成为旋转的分界点,因此,查找一个旋转之后数组的最小值可以变成查找一个旋转数组的旋转点。而我们仍然可以发现,在旋转点之前的序列是递增有序的,而在旋转点之后的序列也是递增有序的,因此可以这样判断:

  1. 取数组的中间值;

  2. 如果中间值比最左值大且比最右值小,那么这个数组就是递增数组旋转幅度为0,最小值就为数组第一个值,直接返回;

  3. 如果中间值比左边一个数小且比右边一个数小,那么中间值就为旋转点也就是最小值,直接返回;

  4. 如果中间值比最左值大且比最右值大,那么中间值往左一定是递增有序的,而旋转点一定在中间值往右,将范围缩到中间值右半边重新从第1步开始;

  5. 如果中间值比最左值小且比最右值小,那么中间值往右一定是递增有序的,而旋转点一定在中间值往左,将范围缩到中间值左半边重新从第1步开始;


    上面的分析其实是相当于在用二分查找来做,这样就将时间复杂度降为了O(lgN),下面用代码来实现:

#include <iostream>#include <assert.h>using namespace std;int find_min_num(const int *arr, size_t n){    assert(arr && n);     int left = 0;    int right = n-1;    int mid = (right-left)/2;    while(left < right)    {           if((arr[left] <= arr[mid]) && (arr[mid] <= arr[right]))        {            break;//当数组区间为递增时,最小值就为最左值        }        else if((arr[mid-1] > arr[mid]) && (arr[mid+1] > arr[mid]))        {            return arr[mid];//当取到的中间值就为旋转点时,最小值就为中间值        }        else if((arr[left] <= arr[mid]) && (arr[mid] >= arr[right]))        {            left = mid + 1;//当中间值比左边大且比右边大时        }        else        {            right = mid - 1;//除去上面的三种情况就只剩一种了,那就是中间值比左线小且比右边小        }        mid = (right-left)/2 + left;    }       return arr[left];}int main(){    int arr[] = {8, 9, 2, 3, 4, 5, 6, 7};        int ret = find_min_num(arr, sizeof(arr)/sizeof(arr[0]));    cout<<"the min number is: "<<ret<<endl;    return 0;}


运行程序,输出结果为2;

wKioL1com5CixJT5AAAM-xnU0SE147.png

可以将数组设定为不同的情况来检验。



《完》

本文出自 “敲完代码好睡觉zzz” 博客,请务必保留此出处http://2627lounuo.blog.51cto.com/10696599/1769837

在Java中,处理旋转排序数组(例如,`[4, 5, 6, 7, 0, 1, 2]`)并找到最小元素可以采用二分查找的方法。这是因为虽然数组看起来像是随机分布的,但是我们知道它一定是在某一点(枢轴)之后开始旋转的,所以旋转部分还是有序的。 首先,我们可以假设第一个元素最小值,然后从第二个元素开始进行比较。如果当前元素小于已知的最小值,则枢轴不可能在其右侧,因为右侧是递增的。所以我们每次都将搜索范围缩小一半,直到找到最小元素或者确定整个剩余部分都是大于当前最小值的。 以下是简单的Java代码实现: ```java import java.util.Arrays; import java.util.Random; public class RotateArray { public static int findMin(int[] nums) { if (nums == null || nums.length <= 1) { return Arrays.stream(nums).min().getAsInt(); } int left = 0, right = nums.length - 1; while (left < right) { int mid = left + (right - left) / 2; // 如果中间元素大于左边界,说明最小值在左半边 if (mid > 0 && nums[mid] >= nums[left]) { right = mid - 1; } else { // 否则,最小值在右半边或就是左边界 left = mid + 1; } } return nums[left]; } public static void main(String[] args) { Random rand = new Random(); int[] nums = new int[10]; // 或者你想要的任意长度 for (int i = 0; i < nums.length; i++) { nums[i] = rand.nextInt(100); // 生成随机整数填充数组 } Arrays.sort(nums); // 先对数组进行排序 System.out.println("原始数组: " + Arrays.toString(nums)); int minElement = findMin(nums); System.out.println("最小元素: " + minElement); } } ``` 在这个例子中,`findMin`方法会返回旋转数组中最小元素。注意这个解决方案假定了输入数组至少包含两个元素,并且不会改变原数组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值