java数组求最大两数相加_在O(N)时间内求解 正数数组中 两个数相加的 最大值

一,问题描述

给定一个正数数组arr(即数组元素全是正数),找出该数组中,两个元素相加的最大值,其中被加数的下标大于加数的下标。由加法运算的可逆性,j >i 这个条件可以去掉。

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

在数组arr中没有重复的元素情况下,若被加数的下标可以等于加数的下标,则该问题变成了寻找正数数组arr中最大值的元素了。因为 max{arr[i]} + max{arr[i]} 一定比 max{arr[i]} + arr[j] 大,其中arr[j]为数组中的任意某个元素。

而《数据结构与算法分析 Java语言描述》Mark Allen Weiss著 书中第37页 2.28 题中并没有指出数组arr中的元素不通重复。

二,求解思路

有两种思路,一种是对数组中的每个元素,求出该元素与它后面元素的和,然后记录下最大的。

如,对于下标为 i 的元素,for each j belongs to [i+1, arr.length)需要求出 sum=arr[i]+arr[j] 其中,i belongs to [0,arr.length) and j >=i

这算法的时间复杂度为O(N^2)

第二种思路是,先将加数初始化为下标为0的那个元素(arr[i]=arr[0]),然后,j 往后扫描,若遇到比arr[i]大的元素,则下标 i=j。也就是说,i 总是记录比当前arr[i]更大的元素(贪心思想)。

更详细的解释,类似于这篇文章

代码如下:

1 //O(N). find out the max sum of two numbers in a positive array

2 public static int maxSum(int[] arr){3 int i = 0;4 int max = 0;//数组中所有的元素都是正数

5 intaddValue;6 for(int j = 1; j < arr.length; j++){7 addValue = arr[i] +arr[j];8 if(addValue >max)9 max =addValue;10 if(arr[j] - arr[i] > 0)11 i = j;//记录更大的arr[i]

12 }13 returnmax;14 }

三,运行时间的比较

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

机器环境如下:

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

时间比较如下:

数组大小        maxSum运行时间(O(N))       maxSum2算法2运行时间(O(N^2))

100*100             1                                        27

200*100             1                                        68

300*100             2                                        133

500*100             3                                        359

此外,按照同样的思路,也可以求解两个数相加的最小值了,哈哈。。。。

求两数相加的最小值,也同样是每次贪心,贪一个较arr[i]更小的值即可,这简直和求解两数相减的最大值一模一样!!!

代码如下:

1 public static int minSum(int[] arr){2 int min =Integer.MAX_VALUE;3 int i = 0;4 intaddValue;5 for(int j = 1; j < arr.length; j++){6 addValue = arr[j] +arr[i];7 if(addValue

再扩展一下:还可以计算三个数相加的最大值。还是同样的思路,当碰到比上一次运算中的 加数 更大的数时,则把该数替换掉原来加数中最小的那个加数。(三数相加,视为有三个加数。。。^-^)

再扩展一下,是不是感觉到这个问题和 求解最大子序列和 有点联系了?  二者都是直接跳过某些不需要“关注”的元素,并总是“贪心”出 下一个候选元素。

完整代码如下:

1 public classMaxSum {2

3 //O(N). find out the max sum of two numbers in a positive array

4 public static int maxSum(int[] arr){5 int i = 0;6 int max = 0;//数组中所有的元素都是正数

7 intaddValue;8 for(int j = 1; j < arr.length; j++){9 addValue = arr[i] +arr[j];10 if(addValue >max)11 max =addValue;12 if(arr[j] - arr[i] > 0)13 i = j;//记录更大的arr[i]

14 }15 returnmax;16 }17

18

19 public static int maxSum2(int[] arr){20 int max = 0;21 intaddValue;22 for(int i = 0; i < arr.length; i++){23 for(int j = i+1; j < arr.length; j++){24 addValue = arr[j] +arr[i];25 if(addValue >max)26 max =addValue;27 }28 }29 returnmax;30 }31

32 public static voidmain(String[] args) {33 int[] arr = C2_2_8.algorithm3(100*100*10);34

35 long start =System.currentTimeMillis();36 int r =maxSum(arr);37 long end =System.currentTimeMillis();38 System.out.println("maxValue=" + r + " O(N)'s time:" + (end -start));39

40 long start2 =System.currentTimeMillis();41 int r2 =maxSum2(arr);42 long end2 =System.currentTimeMillis();43 System.out.println("maxValue=" + r2 + " O(N^2)'s time:" + (end2 -start2));44 }45 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值