【算法学习系列】07 - 无序数组中的局部最小值问题

news2024/10/6 1:40:18

文章目录

  • 说明
  • 约束条件
  • 简单说下思路
  • 解决方案
    • 随机无序数组样本生成器
    • 算法实现
    • 验证代码
    • 进行大样本随机测试验证算法正确性

说明


在算法中,局部最小值是指一个函数在一个局部范围内的最小值。

具体而言,如果一个函数在一个小区间内的取值都比该区间内的其他取值要小,那么该点就被称为局部最小值。

在算法中,寻找函数的局部最小值通常是一个重要的优化问题。

约束条件


  • 无序数组,相邻位置数组元素的的值大小不相等
  • 找到数组中某个局部最小值的下标

简单说下思路


  • 数组长度为 1 :局部最小值就是它自己。

  • 数组长度为 2 :较小的值是局部最小值。

  • 数组长度为 3 及以上

假设数组长度为 N(N >= 3)

C1:那么首先对比第 0 个位置和第 1 个位置的值大小;如果第 0 个位置的值更小,那第 0 个位置就是数组中的一个局部最小值位置。

C2:如果情况 C1 没找到最小值,那就继续寻找局部最小值,这时候可以对比第 N-1 个位置和第 N-2 个位置的值大小。如果第 N-1 个位置的值更小,那第 N-1 个位置就是数组中的一个局部最小值位置。

C3:如果情况 C1 和 C2 都没找到最小值,这时候说明第 0 个位置到第 1 个位置的值是下降趋势,第 N-2 个位置到第 N-1 个位置的值是上升趋势。如下图示:

在这里插入图片描述
由上图例子可知,在数组中,第 0 个位置和 第 5 个位置之间必存在一个局部最小值。

这时候我们对数组存在局部最小值的区间(0, N-1)进行二分,找到中间位置((0 + (N-1) )/ 2),然后对比中间位置跟相邻位置的值的大小:

1、如果此时中间位置的值最小,说明中间位置就是数组中的一个局部最小值位置;
2、如果中间位置的值不是最小值,那就可以知道中间位置跟相邻位置的值大小是上升还是下降趋势,然后进一步缩小存在局部最小值的区间范围。
3、再根据缩小后的区间继续进行二分判断,直至找到局部最小值,并且是肯定能找到的。

解决方案


有了上面的思路,我们下面开始来实现,并用对数器进行验证。

随机无序数组样本生成器

数组中相邻位置值的大小不相等。工具类如下:

package com.example.myapplication.util;

public class ArrayUtil {

    private volatile static ArrayUtil arrayUtil;

    private ArrayUtil() {
    }

    public static ArrayUtil instance(){
        if (arrayUtil == null){
            synchronized (ArrayUtil.class){
                if (arrayUtil == null){
                    arrayUtil = new ArrayUtil();
                }
            }
        }
        return arrayUtil;
    }

    // 生成无序随机数组,长度和元素值都是随机,且相邻位置的值不相等
    public static int[] getRandomArrayPosNotEqual(int maxLen, int maxValue){
        int randomLen = (int)(Math.random() * maxLen);
        int[] randomArr = new int[randomLen];
        if (randomLen > 0){
            randomArr[0] = (int)(Math.random() * maxValue);
            for (int i = 1; i < randomLen;i++){
                do {
                    randomArr[i] = (int)(Math.random() * maxValue);
                }while (randomArr[i] == randomArr[i - 1]);
            }
        }
        return randomArr;
    }

    // 生成随机数组,长度和元素值都是随机(相邻位置值可能相等)
    public static int[] getRandomArray(int maxLen, int maxValue){
        int randomLen = (int)(Math.random() * maxLen);
        int[] randomArr = new int[randomLen];
        if (randomLen > 0){
            for (int i = 0; i < randomLen;i++){
                randomArr[i] = (int)(Math.random() * maxValue);
            }
        }
        return randomArr;
    }

}

算法实现

算法问题解决方案,代码实现如下:

	// 实现局部最小值算法 找到数组中某个局部最小值的下标并返回
    // 数组无序,且相邻位置的元素值不相等
    private int getLocalMinInArray(int[] arr){
        if (arr == null || arr.length == 0){
            return -1;
        }
        int len = arr.length;
        if (len == 1){
            return 0;
        }
        if (arr[0] < arr[1]){
            return 0;
        }
        if (arr[len - 1] < arr[len - 2]){
            return (len - 1);
        }

        // 示例: [1262, 134, 701, 749, 465, 1333]
        int min = -1;
        int L = 0, R = len - 1;
        // 保证比较的数组中至少存在3个数组元素,防止边界条件异常:例如数组下标越界的异常
        while (L < (R - 1)){
            int mid = (L + R) / 2;
            if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]){
                return mid;
            }

            if (arr[mid] > arr[mid - 1]){
                R = mid - 1;
                continue;
            }

            if (arr[mid] > arr[mid + 1]){
                L = mid + 1;
                continue;
            }
        }

        // 比较数组中还剩两个值的情况 哪个小就返回哪个对应的下标
        min = L;
        if (arr[L] > arr[R]){
            min = R;
        }

        return min;
    }

代码实现跟上面说的思路是一样的。

  • 如果数组下标不存在,则返回 -1。

验证代码

获取到了数组中的局部最小值下标后,我们再来实现一个验证局部最小值是否正确的代码。如下:

	// 验证数组的局部最小值下标是否正确
    private boolean checkLocalMinIndex(int[] arr, int min){
        if (arr.length == 0){
            return (min == -1);
        }
        if (arr.length == 1){
            return (min == 0);
        }
        int minLeft = min - 1;
        int minRight = min + 1;
        if (minLeft == -1 && arr[min] < arr[minRight]){
            // 第一个是局部最小值
            return true;
        }
        if (minRight == (arr.length) && arr[min] < arr[minLeft]){
            // 最后一个是局部最小值
            return true;
        }
        // 中间某个位置是局部最小值
        if (arr[min] < arr[minLeft] && arr[min] < arr[minRight]){
            return true;
        }
        return false;
    }

进行大样本随机测试验证算法正确性

	private void testLocalMinInArray(){
        System.out.println(":> 测试开始");
        int maxLen = 10;
        int maxValue = 2000;
        int testCount = 100000;
        for (int i = 0;i < testCount;i++){
            int[] randomArr = ArrayUtil.instance().getRandomArrayPosNotEqual(maxLen, maxValue);
            int min = getLocalMinInArray(randomArr);
            if (!checkLocalMinIndex(randomArr, min)){
                System.out.println(":> randomArr = " + Arrays.toString(randomArr));
                System.out.println(":> 获取数组局部最小值下标min不正确,min = " + min);
                break;
            }

            if (i == testCount - 1){
                System.out.println(":> 最后一个数组:" + Arrays.toString(randomArr));
                System.out.println(":> 最后一个数组,局部最小值下标:" + min);
            }
        }
        System.out.println(":> 测试结束");
    }
  • 多次测试均通过,如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

故求取无序数组局部最小值下标算法正确。


“Peace Love Respect”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/588574.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++:STL--priority_queue

文章目录 一.STL设计思想:容器适配器STL--stack的代码设计STL--queue的代码设计stack和queue的默认容器适配器deque的数据结构解析deque的存储结构示意图 二.C仿函数仿函数示例 三.STL--priority_queue(优先级队列)1.C优先级队列的数据结构2.priority_queue的实现框架比较函数(…

chatgpt赋能python:Python中创建画布的函数——matplotlib

Python中创建画布的函数——matplotlib Python作为一种强大的编程语言&#xff0c;拥有许多重要且广泛应用的模块和库。其中&#xff0c;matplotlib是一种用于制作高质量的图形和图表的库&#xff0c;而创建画布的函数便是其基础功能之一。 什么是matplotlib&#xff1f; Ma…

C语言---初始C语言

1、初始C语言 1、编译器主要有&#xff1a;Clang、GCC、WIN-TC、MSVC、Turbo C等 什么是编译&#xff1f; test.c----------------------------->test.exe 这个过程需要经过编译、链接等过程&#xff0c;而众多编译器实现的功能就是把我们写的test.c进行编译。 2、VS20…

如何把“困在”内网的数据释放,进行安全的流转传输呢?

互联网大时代&#xff0c;数据的生产使用与互联网紧密相关&#xff0c;但数据安全和网络安全却既有联系又互不相同。数据安全和网络安全的突出区别是核心主体不同&#xff0c;数据安全关注的数据全生命周期的安全&#xff0c;而网络安全则是侧重保障网络体系和网络环境的安全性…

硬卷完了!低代码打怪升级进阶成神之路(2023年最新版)

一、背景 应用开发周期长一直是IT部门和业务部门面临的问题。 IT部门总是被新的应用需求弄得不堪重负。他们不可能完成业务部门想要完成的每一个项目。同时&#xff0c;业务部门的用户厌倦了等待&#xff0c;并开始完全绕过IT部门。 今天&#xff0c;我们来探索一下“低代码开发…

制药企业高效过滤器检漏参考法规、方法及操作步骤

对制药企业来讲&#xff0c;高效过滤器检漏主要是现场检漏&#xff0c;通过DOP法来发现滤器本身及运输、安装过程中可能存在的问题。常使用气溶胶光度计及多分散气溶胶进行检漏。依据的标准是2010药品GMP指南(测试方法采用ISO14644-3)。 对于制药企业来说&#xff0c;高效过滤器…

自动驾驶TPM技术杂谈 ———— 边缘检测

文章目录 介绍边缘检测与微分运算离散信号的差分滤波Robert算子Prewitt算子Sobel算子拉普拉斯算子 介绍 计算机视觉&#xff08;Computer Vision&#xff0c;CV&#xff09;是一门使用计算机模拟生物视觉的学科&#xff0c;目的是使用计算机代替人眼实现对目标的识别、分类、跟…

3.2. 数学类(Math、BigInteger、BigDecimal)

1. Math类 Math类提供了一些基本的数学函数&#xff0c;如求平方根、绝对值、三角函数等。它是一个final类&#xff0c;并且所有的方法都是static的&#xff0c;因此无需创建对象&#xff0c;直接使用类名调用方法即可。 以下是Math类的一些常用方法&#xff1a; abs(double…

抖音seo源码-抖音搜索源码-抖音下拉词-抖音关键词排名系统搭建

为了优化抖音平台上的内容&#xff0c;开发抖音关键词排名系统成为了必要的措施。该系统可以针对搜索结果和下拉词进行分析&#xff0c;为用户提供更准确的搜索结果。为实现这一目标&#xff0c;开发团队进行了大量的市场调查和用户研究。 在开发过程中&#xff0c;团队利用了…

mysql8+忘记密码的详细解决方法

mysql8忘记密码的详细解决方法 不同的版本&#xff0c;可能处理的方式不一样&#xff0c;这里说一下8以上的版本处理密码忘记的问题&#xff0c;windows系统。 一.问题&#xff1a; 太久没用mysql &#xff0c;忘记了原先的root密码 二&#xff1a;解决 1.关闭mysql服务,我的…

代码随想录算法训练营第四十八天 | 力扣 198.打家劫舍, 213.打家劫舍II, 337.打家劫舍III

198.打家劫舍 题目 198. 打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警…

word文档生成PDF文档时候自动生成书签方法

0 Preface/Foreword 在日常工作中&#xff0c;经常需要写技术文档&#xff0c;为了排版美观&#xff0c;一般会选择word&#xff0c;这样就可以生成目录。 word文件可以很方便生产PDF文档&#xff0c;方便分享给同事。 在阅读PDF文档时&#xff0c;看到有些PDF文档在左侧有一…

Kafka入门(安装和SpringBoot整合)

文章目录 一、Docker安装Kafka1. 创建网络2. 安装zookeeper3. 安装Kafka 二、Kafka介绍1. Kafka简介 三、SpringBoot整合Kafka1. 引入pom依赖2. application.propertise配置3. Hello Kafka(Producer)4. Consumer Kafka5. 带回调的生产者6. 自定义分区器7. kafka事务提交8. 指定…

如何将 O2OA (翱途) 集成到阿里钉钉

O2OA 平台拥有配套的原生开发的安卓和 IOS 移动 APP&#xff0c;可以以微应用的方式集成到阿里钉钉&#xff0c;同步钉钉的企业通讯录作为本地组织人员架构&#xff0c;并且可以将待办等通知直接推送到钉钉进行消息提醒。本篇主要介绍如何将 O2OA 集成到阿里钉钉实现钉钉办公。…

欧科云链(01499.HK)成格林威治经济论坛钻石级行业独家合作伙伴

5月30日讯&#xff0c;欧科云链控股有限公司&#xff08;“欧科云链控股”&#xff0c;1499.HK&#xff09;官宣成为全球高端经济峰会格林威治经济论坛(Greenwich Economic Forum&#xff0c;下称GEF论坛)的钻石级行业独家合作伙伴。该论坛将于6月15日至16日&#xff0c;首次在…

【维生素C语言】附录:Github 使用教学

&#x1f451; 全新Python高级软件实践专栏&#xff1a; 一起玩蛇啊 &#x1f449; 《一起玩蛇》&#x1f40d; &#x1f4ad; 写在前面&#xff1a;本章我们将介绍 Git 的基本使用方法&#xff0c;包括注册 GitHub 账号、设置 Git、创建本地存储库、复制本地存储库、导入远程…

electron24整合vite4+vue3创建跨端桌面程序

基于Electron集成Vite4.x构建桌面端exe应用 electron24-vite4-vue3 运用最新版本electron结合vite4.x创建vue3桌面端应用程序。 // 版本信息 vite: ^4.3.2 vue: ^3.2.47 electron: ^24.4.0 electron-builder: ^23.6.0创建vitevue3项目 // 初始化项目 npm create vitelatest el…

Echarts绘制K线图,文末源码地址!

文章目录 K线图Apache Echarts绘制K线图完整源码地址 本文中仅展示部分关键代码&#xff0c;文末有完整源码地址&#xff0c;欢迎下载&#xff01; K线图 K线图是一种常见的股票价格走势图表&#xff0c;它是用于显示股票价格变化的一种图表形式。K线图以日、周、月等周期为单…

聊聊分布式解决方案Saga模式

Saga模式 Saga模式使用一系列本地事务来提供事务管理&#xff0c;而一个本地事务对应一个Saga参与者&#xff0c;在Saga流程里面每一个本地事务只操作本地数据库&#xff0c;然后通过消息或事件来触发下一个本地事务&#xff0c;如果其中一个本地事务失败了&#xff0c;Saga就…

一文搞懂激活函数(Sigmoid/ReLU/LeakyReLU/PReLU/ELU)

深度学习算法之前的机器学习算法&#xff0c;并不需要对训练数据作概率统计上的假设&#xff1b;但为了让深度学习算法有更好的性能&#xff0c;需要满足的关键要素之一&#xff0c;就是&#xff1a;网络的输入数据服从特定的分布&#xff1a; 数据分布应该是零均值化的&#…