本文主要是介绍C/C++ BM21 旋转数组的最小数字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 前言
- 题目
- 解决方案一
- 1.1 思路阐述
- 1.2 源码
- 解决方案二
- 2.1 思路阐述
- 2.2 源码
- 总结
前言
查找算法的适用条件以及找到题目最核心的诉求是解决问题的关键。
题目
描述
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围: 1 ≤ n ≤ 10000 1≤n≤10000 1≤n≤10000,数组中任意元素的值: 0 ≤ v a l ≤ 10000 0≤val≤10000 0≤val≤10000
要求:空间复杂度: O ( 1 ) O(1) O(1),时间复杂度: O ( l o g n ) O(logn) O(logn)
示例1
输入: [ 3 , 4 , 5 , 1 , 2 ] [3,4,5,1,2] [3,4,5,1,2]
返回值: 1 1 1
示例2
输入: [ 3 , 100 , 200 , 3 ] [3,100,200,3] [3,100,200,3]
返回值: 3 3 3
解决方案一
1.1 思路阐述
题目说的旋转什么的,都不看,精简一下就是一个数组里面找最小值。
不考虑时间复杂度和空间复杂度的话,一个for循环遍历搞定。
1.2 源码
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param nums int整型vector * @return int整型*/int minNumberInRotateArray(vector<int>& nums) {int min=nums[0];for (int i=0; i<nums.size()-1; i++) {if(nums[i]<=min){min=nums[i];}}return min;}
};
解决方案二
2.1 思路阐述
看题目给的时间复杂度和空间复杂度,大概率就是一种分治的思想,那就是二分查找。
题目的数列有一个特性,AB两个子序列组成一个序列C,现在变成了BA,由于C序列是非递减序列,所以其实B序列中任意一个数都大于A。
用二分法来做的步骤如下:
step 1:双指针指向旋转后数组的首尾,作为区间端点。
step 2:若是区间中点值大于区间右界值,则最小的数字一定在中点右边。(这里和序列特性有关系)
step 3:若是区间中点值等于区间右界值,则是不容易分辨最小数字在哪半个区间,比如[1,1,1,0,1],应该逐个缩减右界。
step 4:若是区间中点值小于区间右界值,则最小的数字一定在中点左边。
step 5:通过调整区间最后即可锁定最小值所在。
2.2 源码
class Solution {
public:int minNumberInRotateArray(vector<int>& nums) {int i=0,mid,j=nums.size()-1;while (i<j) {mid=i+(j-i)/2;if(nums[mid]>nums[j]){i=mid+1;}else if(nums[mid]==nums[j]){j--;}else{j=mid;}}return nums[i];}
};
总结
遇到有序数列的一种查找,如果对时间复杂度有要求,要考虑二分查找。
这篇关于C/C++ BM21 旋转数组的最小数字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!