两种方法求解 正数数组中 两个数相减 的最大值

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介:

一,问题描述

给定一个正数数组arr(即数组元素全是正数),找出该数组中,两个元素相减的最大值,其中被减数的下标不小于减数的下标。

即求出: maxValue = max{arr[j]-arr[i] and j >= i}

 

二,求解思路

下面采用两种不同的算法来求解,第一种算法的时间复杂度为O(N),第二种算法的时间复杂度为O(N^2)。

算法一思路如下:(初始时减数为arr[0],然后算法不断记录比当前减数更小的减数)

maxValue初始化为0,因为当 i==j 时,arr[j] - arr[i] = 0,故 maxValue的值不可能为负数。

因此将下标 i 初始化为0,j 从下标1处开始向后扫描,并计算sub = arr[j]-arr[i]

若sub大于maxValue,则更新maxValue的值。

否则,若sub小于0,意味着找到一个新的数组元素,该数组元素比 arr[i]的值要小,则更新下标 i.

 

为什么这样可以?

因为:当计算 sub = arr[j]-arr[i]时,arr[i]越小,则得到的sub越大。而下标 i 不断标记更小的减数,后面的元素arr[j]与 更小的减数相减才能得到更大的差值。

比如,下图所示数组:

 

arr[0]=18,当j=2时,max=arr[2]-arr[0]=8。当遍历到arr[3]=12时,由于12小于18,故把下标 i 由 0 更新为 3。不需要”关注“下标为1和2的这两个元素。因为,

若在 j>3 后面有元素使得 arr[j]-arr[1] 或者 arr[j]-arr[2]>maxValue,则该arr[j]-arr[0]一定比 arr[j]-arr[1]更大,因为arr[1]和 arr[2]都比arr[0]大。

同理:也不需要关注元素值为12 和 元素值为10之间的元素,因为,若后面某个元素减去某个 “12 到 10之间的元素(16、18、22)”比maxValue大,那么它减去12一定更大

这样,下标 i 记录的总是下一个比 arr[i] 更小的值(这有点类似于贪心算法的味道,每次总是贪比当前值更小的一个值,而不是如算法2中那样依次遍历数组中的每个元素。

 

代码如下:

复制代码
 1     //算法复杂度O(N). 找出数组arr中两个数相减的最大值
 2     public static int maxValueOfSubtraction(int[] arr){ 
 3         int max = 0;// when j == i
 4         int i = 0;
 5         int sub;
 6         for(int j = 1; j < arr.length; j++){
 7             sub = arr[j] - arr[i];
 8             if(sub > max)
 9                 max = sub;
10             else if(sub < 0)//means there is a number smaller than a[i](i initial value is 0)
11                 i = j;
12         }
13         return max;
14     } 
复制代码

 

算法二:

就是一个很普通的方法。求出 数组中所有下标大的元素减去下标小的元素,找出其中的最大值即可。代码如下:

复制代码
 1     //O(N^2) 找出数组arr中两个数相减的最大值
 2     public static int maxValueSub(int[] arr){
 3         int max = 0;
 4         int sub;
 5         for(int i = 0; i < arr.length; i++){
 6             for(int j = i+1; j < arr.length; j++){
 7                 sub = arr[j] - arr[i];
 8                 if(sub > max)
 9                     max = sub;
10             }
11         }
12         return max;
13     }
复制代码

 

一个错误的解法:

由于题目中要求的是 被减数的下标要大于减数的下标,故下面解法是错误的:

依次扫描数组中的每个元素,找出数组元素中的最大值和最小值。最大值减去最小值 即为两个元素相减的最大值。

错误的原因是:最大值元素的下标 可能 比 最小值元素的下标要小。

错误解法代码如下:

复制代码
 1     public static int maxValueSub3(int[] arr){
 2         int min, max;
 3         int indexM = -1;int indexm = -1;
 4         min = max = arr[0];
 5         for(int i = 1; i < arr.length; i++){
 6             if(arr[i] > max)
 7             {
 8                 max = arr[i];
 9                 indexM = i;
10             }
11             else if(arr[i] < min){
12                 min = arr[i];
13                 indexm = i;
14             }
15         }
16         System.out.println("indexM" + indexM + " indexm:" + indexm);
17         return max - min;
18     }
复制代码

 

三,运行时间的比较

采用 这篇文章 中提到的随机数生成算法 来随机生成一个数组,然后比较上面两个算法的运行时间。

机器环境如下:

OS:win7 64bit、RAM:6GB、CPU:Pentium(R)Dual-Core E5800@3.2GHz

时间比较如下:

数组大小        算法1运行时间       算法2运行时间

100*100               1                        61

200*100               3                        158

400*100               2                        568

500*100               2                        878

100*100*10         4                        3451

 

整个代码如下:

复制代码
 1 /*
 2  * given an array, find out the max value of two numbers's distraction.
 3  * max{a[j]-a[i]} under the condition of j>=i
 4  */
 5 public class MaxValue {
 6     
 7     //算法复杂度O(N). 找出数组arr中两个数相减的最大值
 8     public static int maxValueOfSubtraction(int[] arr){ 
 9         int max = 0;// when j == i
10         int i = 0;
11         int sub;
12         for(int j = 1; j < arr.length; j++){
13             sub = arr[j] - arr[i];
14             if(sub > max)
15                 max = sub;
16             else if(sub < 0)//means there is a number smaller than a[i](i initial value is 0)
17                 i = j;
18         }
19         return max;
20     } 
21     
22     //O(N^2) 找出数组arr中两个数相减的最大值
23     public static int maxValueSub(int[] arr){
24         int max = 0;
25         int sub;
26         for(int i = 0; i < arr.length; i++){
27             for(int j = i+1; j < arr.length; j++){
28                 sub = arr[j] - arr[i];
29                 if(sub > max)
30                     max = sub;
31             }
32         }
33         return max;
34     }
35     
36     
37     public static void main(String[] args) {
38         int[] arr = C2_2_8.algorithm3(100*100*10);
39 
40         long start = System.currentTimeMillis();
41         int r = maxValueOfSubtraction(arr);
42         long end = System.currentTimeMillis();
43         System.out.println("maxValue=" + r + "  O(N)'s time:" + (end -start));
44         
45         long start2 = System.currentTimeMillis();
46         int r2 = maxValueSub(arr);
47         long end2 = System.currentTimeMillis();
48         System.out.println("maxValue=" + r2 + "  O(N^2)'s time:" + (end2 - start2));
49     }
50 }


相关文章
|
运维 NoSQL 安全
【最佳实践】高可用mongodb集群(1分片+3副本):规划及部署
结合我们的生产需求,本次详细整理了最新版本 MonogoDB 7.0 集群的规划及部署过程,具有较大的参考价值,基本可照搬使用。 适应数据规模为T级的场景,由于设计了分片支撑,后续如有大数据量需求,可分片横向扩展。
2057 1
|
2月前
|
机器学习/深度学习 人工智能 弹性计算
2026阿里云新老用户优惠活动解析:轻量38元起,ECS 99元/199元续费同价,企业享补贴,AI免费体验
阿里云2026年面向新老用户的五大核心优惠活动。轻量应用服务器新用户秒杀低至38元/年,2核4G配置9.9元/月起;云服务器ECS经济型99元/年、通用算力型199元/年,新老同享且续费同价。企业用户可申请5亿算力迁云补贴及出海扶持优惠券,降低规模化上云成本。阿里云百炼推出"先用后返"活动,最高返200元,覆盖全量大模型服务。此外,免费试用中心提供超30款AI产品及7000万tokens零成本体验。
|
9月前
|
存储 机器学习/深度学习 人工智能
硅谷GPU单节点服务器:技术解析与应用全景
“硅谷GPU单节点服务器”代表了在单个物理机箱内集成强大计算能力,特别是GPU加速能力的高性能计算解决方案。它们并非指代某个特定品牌,而是一类为处理密集型工作负载而设计的服务器范式的统称。
|
Linux 数据安全/隐私保护
Linux文件权限调整:chmod指令解析
在日常使用或系统管理中,对 `chmod`的熟练应用是提高工作效率和维持系统稳定性的关键。掌握如何给予或限制权限是每个Linux使用者都应该具备的技能。
751 17
|
7月前
|
传感器 算法 机器人
减速机行业场景化技术方案与数据化选型指南
本文系统解析减速机在新能源、机器人、智能物流等领域的场景化应用,结合15年工程经验与12个典型案例,构建涵盖选型校核、结构优化、维护策略的全流程技术方案,配套数据化计算工具与故障诊断算法,助力实现精准匹配、可靠运行与降本增效。
减速机行业场景化技术方案与数据化选型指南
|
前端开发 JavaScript
Promise.reject()和throw有什么区别?
Promise.reject()和throw有什么区别?
709 154
|
12月前
|
数据采集 存储 BI
数据中台是什么?一文讲清为什么要建设数据中台
数据中台是企业实现数据整合与高效应用的关键平台,能够打通数据孤岛、提升决策效率并降低成本。它通过统一管理、清洗和分发数据,支撑业务创新与实时分析,是企业在数字化转型中的核心基础设施。
|
存储 安全 Go
Map的遍历与判断键是否存在-《Go语言实战指南》
本文介绍了 Go 语言中对 `map` 的常见操作,包括遍历所有项和判断键是否存在。通过 `for range` 可以遍历 `map` 的键值对、仅键或仅值(需忽略键)。注意,`map` 遍历顺序是随机的。判断键是否存在时,使用双赋值语法 `value, ok := map[key]`,其中 `ok` 表示键是否存在。直接访问不存在的键会返回类型的零值,可能导致逻辑错误。掌握这些机制可更安全高效地处理键值对数据。
|
消息中间件 Kafka Go
module declares its path as: github.com/IBM/sarama but was required as: gith
module declares its path as: github.com/IBM/sarama but was required as: gith
|
搜索推荐 C++
【Qt 学习笔记】Qt窗口 | 对话框 | 创建自定义对话框
【Qt 学习笔记】Qt窗口 | 对话框 | 创建自定义对话框
972 4