在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]更大的元素(贪心思想)。
更详细的解释,类似于这篇文章
代码如下:
//O(N). find out the max sum of two numbers in a positive array
public static int maxSum(int[] arr){
int i = 0;
int max = 0;//数组中所有的元素都是正数
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[i] + arr[j];
if(addValue > max)
max = addValue;
if(arr[j] - arr[i] > 0)
i = j;//记录更大的arr[i]
}
return max;
}
三,运行时间的比较
采用 这篇文章中提到的随机数生成算法 来随机生成一个数组,然后比较上面两个算法的运行时间。
机器环境如下:
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]更小的值即可,这简直和求解两数相减的最大值一模一样!!!
代码如下:
public static int minSum(int[] arr){
int min = Integer.MAX_VALUE;
int i = 0;
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[j] + arr[i];
if(addValue < min)
min = addValue;
if(arr[j] - arr[i] < 0)
i = j;
}
return min;
}
再扩展一下:还可以计算三个数相加的最大值。还是同样的思路,当碰到比上一次运算中的 加数 更大的数时,则把该数替换掉原来加数中最小的那个加数。(三数相加,视为有三个加数。。。^-^)
再扩展一下,是不是感觉到这个问题和 求解最大子序列和 有点联系了? 二者都是直接跳过某些不需要“关注”的元素,并总是“贪心”出 下一个候选元素。
完整代码如下:
public class MaxSum {
//O(N). find out the max sum of two numbers in a positive array
public static int maxSum(int[] arr){
int i = 0;
int max = 0;//数组中所有的元素都是正数
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[i] + arr[j];
if(addValue > max)
max = addValue;
if(arr[j] - arr[i] > 0)
i = j;//记录更大的arr[i]
}
return max;
}
public static int maxSum2(int[] arr){
int max = 0;
int addValue;
for(int i = 0; i < arr.length; i++){
for(int j = i+1; j < arr.length; j++){
addValue = arr[j] + arr[i];
if(addValue > max)
max = addValue;
}
}
return max;
}
public static void main(String[] args) {
int[] arr = C2_2_8.algorithm3(100*100*10);
long start = System.currentTimeMillis();
int r = maxSum(arr);
long end = System.currentTimeMillis();
System.out.println("maxValue=" + r + " O(N)'s time:" + (end -start));
long start2 = System.currentTimeMillis();
int r2 = maxSum2(arr);
long end2 = System.currentTimeMillis();
System.out.println("maxValue=" + r2 + " O(N^2)'s time:" + (end2 - start2));
}
}
在O(N)时间内求解 正数数组中 两个数相加的 最大值的更多相关文章
- 2016网易实习生编程题:数组中两个数的和等于sum
题目 找出数组中两个数的和等于sum的这两个数 解题 这个题目做过很多次了,利用HashMap,key为 sum-A[i] value为 i 当 加入HashMap时候A[i] 已经存在map中,ge ...
- LeetCode 421. 数组中两个数的最大异或值(Maximum XOR of Two Numbers in an Array) 71
421. 数组中两个数的最大异或值 421. Maximum XOR of Two Numbers in an Array 题目描述 给定一个非空数组,数组中元素为 a0, a1, a2, - , a ...
- Java实现 LeetCode 421 数组中两个数的最大异或值
421. 数组中两个数的最大异或值 给定一个非空数组,数组中元素为 a0, a1, a2, - , an-1,其中 0 ≤ ai < 231 . 找到 ai 和aj 最大的异或 (XOR) 运算 ...
- [Swift]LeetCode421. 数组中两个数的最大异或值 | Maximum XOR of Two Numbers in an Array
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...
- 421 Maximum XOR of Two Numbers in an Array 数组中两个数的最大异或值
给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 .找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, j < ...
- 一个数组中两个数的和为N,找出这两个数字的下标
分析,两个数字的和为N.那么这两个数字是否是唯一的呢?输出的下标是否是第一对出现的呢? 1,我们假设这两个数字是唯一的 和是唯一的,那么其中一个数字越大,另一个数字就越小.想到大小关系,我们就想到了排 ...
- LeetCode 数组中两个数的最大异或值
题目链接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/ 题目大意: 略. 分析: 字典树 + 贪心. ...
- 获取数组中多个相加等于0的一组数字 javascript
//获取数组中两个相加等于0的一对数字,比如[ [ -10, 10 ], [ -5, 5 ] ] var arr=[-5,10,1,-10,3,4,5,9] //对数组进行排序 arr.sort(fu ...
- Java泛型01--任意数组中两元素交换
package com.zl.generic; /** * 交换“任意”数组 中两个元素 */ public class GenericSwapArray { public static void m ...
随机推荐
- Oracle的简单的创建dblink以及进行数据迁移的方法
1. 创建dblink 语法如下: create public database link zhaobsh connect to lcoe739999 identified by Test6530 u ...
- 关于封装了gevent的request grequest库的使用与讨论
最近迷上了gevent所以研究很多gevent相关的东西. 但是我现在不想写相关gevent和greenlet的东西.因为这一块内容实在太多太大太杂,我自己也还没有完全弄明白,所以等我完全搞清楚测试也 ...
- html5應用緩存
HTML5使用了應用緩存,就是web應用緩存,使得在離線狀態下可以訪問web'應用. 應用緩存的優點: 離線訪問-可以在無網的狀態下訪問應用 速度-有緩存的應用加載更快 瀏覽器負載-瀏覽器只從服務器加 ...
- oftype 指的是集合的类型
- 牛客网练习赛7-B-购物
在遥远的东方,有一家糖果专卖店. 这家糖果店将会在每天出售一些糖果,它每天都会生产出m个糖果,第i天的第j个糖果价格为C[i][j]元. 现在的你想要在接下来的n天去糖果店进行选购,你每天可以买多个糖 ...
- BZOJ2277[Poi2011]Strongbox——数论
题目描述 Byteasar is a famous safe-cracker, who renounced his criminal activity and got into testing and ...
- Java监听器Listener的使用详解
监听器用于监听Web应用中某些对象的创建.销毁.增加,修改,删除等动作的发生,然后作出相应的响应处理.当监听范围的对象的状态发生变化的时候,服务器自动调用监听器对象中的方法.常用于统计网站在线人数.系 ...
- 自学Python5.3-类和对象的简单操作
自学Python之路 自学Python5.3-类和对象的简单操作 1. 定义一个类 定义一个类的格式如下: class 类名: 方法列表 举例1 : class Cat: #定义一个Cat类 #属性 ...
- BroadcastReceiver 接收系统短信广播
BroadcastReceiver 接收系统短信广播 /* 注册广播: * |--静态注册 (在AndroidManifest .xml 中注册) * <receiver androi ...
- 【BZOJ4830】[HNOI2017]抛硬币(组合计数,拓展卢卡斯定理)
[BZOJ4830][HNOI2017]抛硬币(组合计数,拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 暴力是啥? 枚举\(A\)的次数和\(B\)的次数,然后直接组合数算就好了:\(\display ...