前言
本文含有二分查找算法的知识,如果不是很熟悉,可以参考下这篇文章后再回头看这篇文章会相对比较轻松。
问题描述
现在有一个先升后降/先降后升的数组(不考虑重复),怎么求这两种不同数组的最大值和最小值?
解题思路
我们可以通过二分检索的思路来解决这道题,首先我们要思考的一个问题就是:最值有什么特征?
- 最大值,即为已知的数据中的最大的一个值。
- 最小值,即为已知的数据中的最小的一个值。
通过以上定义,我们不妨转换一下思路;最大/最小 = 大于左右两边的数/小于左右两边的数。那么,我们就可以简单的用代码表示一下最主要的判断条件:
// 最大值 先升后降
if (mid > mid - 1 && mid > mid + 1) {
mid = find;
}
// 最小值 先降后升
if (mid < mid - 1 && mid < mid + 1) {
mid = find
}
那么,就有人要问了:为什么先升后降的最小值/先降后升的最大值不写啊?
首先我们拿到问题需要先观察问题,再去想解决办法。先升后降的最小值和先降后升的最大值我们从下图一看便知晓了:
很明显,问题的答案已经显而易见了。对于以上两种情况的最小值/最大值的求法就是:比较两个端点的值,那个更大就是最大值,那个更小就是最小值。
这一整个问题到这似乎已经结束了。但是,我们这是在最好的情况(恰好能找到且左右端点中间还有至少一个中间值)下去考虑这个问题的。那么,最坏的情况(左右端点寻找到最后一次且中间没有值)下呢?
很简单,我们从上图就可以看出,在最坏的情况下就回到了端点求值的问题,那么我就只需要判断左右两个值那个更大那个更小就可以了。只需要再加一个判断条件就可以了:
if (right - left == 1) {
if (right > left) {
// 右边大就返回right
return right
} else {
// 左边大就返回left
return left
}
}
接下来就开始动手环节了!
源码实现
先升后降:
window.onload = function () {
let array1 = [1, 2, 3, 4, 12, 10, 9, 8, 7, 6, 5]; // 定义一个先升后降的数组
let select; //定义用户的选择
select = +prompt("输入你的选择:1.求最大值 2.求最小值")
let left, right, count, mid; //定义左右端点,中间值以及计次数并作初始化
left = 0;
count = 0;
right = array1.length - 1;
switch (select) {
case 1:
while (left <= right) { // 始终保证有至少一个元素
count++;
mid = parseInt((right - left) / 2); // 取整
// 类二分检索查找最大值
if (array1[mid] > array1[mid - 1] && array1[mid] > array1[mid + 1]) {
alert("最大值为" + array1[mid] + "找了" + count + "次")
return 0;
} else if (array1[mid] > array1[mid - 1] && array1[mid] < array1[mid + 1]) {
left = mid + 1;
} else if (array1[mid] < array1[mid - 1] && array1[mid] > array1[mid + 1]) {
right = mid - 1;
} else if (right - left == 1) {
// 最坏情况下 只剩左右端点
if (array1[right] > array1[left]) {
alert("最大值是" + array1[right] + "找了" + count + "次");
return 0;
} else {
alert("最大值是" + array1[left] + "找了" + count + "次");
return 0;
}
}
}
break;
case 2:
// 求最小值 即求端点值
if (array1[left] < array1[right]) {
count++;
alert("最小值是" + array1[left] + "找了" + count + "次");
} else {
count++;
alert("最小值是" + array1[right] + "找了" + count + "次");
}
break;
}
}
创作不易,希望能够支持一下!
什么是支持呢?
(ノ∇︎〃 )
点个赞,收藏一下,点个关注之类的。
如果你有更好的想法或者发现文章的不足之处,望大家不吝赐教!