《剑指offer》第12天:旋转数组的最小数字
时间:2022-07-23
本文章向大家介绍《剑指offer》第12天:旋转数组的最小数字,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组 {3,4,5,1,2}
为 {1,2,3,4,5}
的一个旋转,该数组的最小值为 1
。
**NOTE:**给出的所有元素都大于 0
,若数组大小为 0
,请返回 0
。
解法
解法一
直接遍历数组找最小值,时间复杂度 O(n)
,不推荐。
public class Solution {
/**
* 获取旋转数组的最小元素
* @param array 旋转数组
* @return 数组中的最小值
*/
public int minNumberInRotateArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int n = array.length;
if (n == 1 || array[0] < array[n - 1]) {
return array[0];
}
int min = array[0];
for (int i = 1; i < n; ++i) {
min = array[i] < min ? array[i] : min;
}
return min;
}
}
解法二
利用指针 p
,q
指向数组的首尾,如果 array[p] < array[q]
,说明数组是递增数组,直接返回 array[p]
。否则进行如下讨论。
计算中间指针 mid
:
- 如果此时
array[p]
,array[q]
,array[mid]
两两相等,此时无法采用二分方式,只能通过遍历区间[p,q]
获取最小值; - 如果此时
p
,q
相邻,说明此时q
指向的元素是最小值,返回array[q]
; - 如果此时
array[mid] >= array[p]
,说明mid
位于左边的递增数组中,最小值在右边,因此,把p
指向mid
,此时保持了p
指向左边递增子数组; - 如果此时
array[mid] <= array[q]
,说明mid
位于右边的递增数组中,最小值在左边,因此,把q
指向mid
,此时保持了q
指向右边递增子数组。
public class Solution {
/**
* 获取旋转数组的最小元素
* @param array 旋转数组
* @return 数组中的最小值
*/
public int minNumberInRotateArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int p = 0;
// mid初始为p,为了兼容当数组是递增数组(即不满足 array[p] >= array[q])时,返回 array[p]
int mid = p;
int q = array.length - 1;
while (array[p] >= array[q]) {
if (q - p == 1) {
// 当p,q相邻时(距离为1),那么q指向的元素就是最小值
mid = q;
break;
}
mid = p + ((q - p) >> 1);
// 当p,q,mid指向的值相等时,此时只能通过遍历查找最小值
if (array[p] == array[q] && array[mid] == array[p]) {
mid = getMinIndex(array, p, q);
break;
}
if (array[mid] >= array[p]) {
p = mid;
} else if (array[mid] <= array[q]) {
q = mid;
}
}
return array[mid];
}
private int getMinIndex(int[] array, int p, int q) {
int minIndex = p;
for (int i = p + 1; i <= q; ++i) {
minIndex = array[i] < array[minIndex] ? i : minIndex;
}
return minIndex;
}
}
测试用例
- 功能测试(输入的数组是升序排序数组的一个旋转,数组中有重复数字或者没有重复数字);
- 边界值测试(输入的数组是一个升序排序的数组,只包含一个数字的数组);
- 特殊输入测试(输入空指针)。
内容展示:
- hdu 1811 Rank of Tetris (并查集+拓扑排序)
- Pycharm常用技巧
- hdu 1598 find the most comfortable road(枚举+卡鲁斯卡尔最小生成树)
- 查询IP地址归属详情
- oracle commit详解
- hdu 4315 Climbing the Hill(阶梯博弈转nim博弈)
- iftop实时网络流量监控工具的安装使用
- hdu 3908 Triple(组合计数、容斥原理)
- hdu 4034 Graph (floyd的深入理解)
- hdu 4033Regular Polygon(二分+余弦定理)
- Debian8配置SSH允许root登陆
- hdu 4405Aeroplane chess(概率DP)
- hdu 3853LOOPS (概率DP)
- cf(#div1 B. Dreamoon and Sets)(数论)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法