【javascript算法】类二分检索求最值

前言

  本文含有二分查找算法的知识,如果不是很熟悉,可以参考下这篇文章后再回头看这篇文章会相对比较轻松。

https://blog.csdn.net/qq_51869518/article/details/127459631?spm=1001.2014.3001.5502https://blog.csdn.net/qq_51869518/article/details/127459631?spm=1001.2014.3001.5502

问题描述

  现在有一个先升后降/先降后升的数组(不考虑重复),怎么求这两种不同数组的最大值和最小值?

解题思路

  我们可以通过二分检索的思路来解决这道题,首先我们要思考的一个问题就是:最值有什么特征?

  • 最大值,即为已知的数据中的最大的一个值。
  • 最小值,即为已知的数据中的最小的一个值。

   通过以上定义,我们不妨转换一下思路;最大/最小 = 大于左右两边的数/小于左右两边的数。那么,我们就可以简单的用代码表示一下最主要的判断条件:

  // 最大值 先升后降
  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;
        }
    }

创作不易,希望能够支持一下!

什么是支持呢?

(ノ∇︎〃 )

点个赞,收藏一下,点个关注之类的。

如果你有更好的想法或者发现文章的不足之处,望大家不吝赐教!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

valiant小东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值