import java.util.*;
/**
* HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。
* 今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。
* 但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?
* 例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。
* 你会不会被他忽悠住?(子向量的长度至少是1)
* Created by ZeHua on 2017/5/29.
*/
public class FindGreatestSumOfSubArray {
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null||array.length==0){
return 0;
}
if(array.length==1){
return array[0];
}
//构建最大和数组
int[] sum = new int[array.length];
for(int i=0,sum_i=0;i<array.length;i++ ){
sum_i=sum_i+array[i];
sum[i]=sum_i;
}
MaxSumQueue queue = new MaxSumQueue(sum);
//开头到末尾的窗口最大值的特殊队列
for(int i=0;i<sum.length;i++){
queue.add(i);
}
int res;
//窗口左端逐步右移,找出子向量的最大和
res = sum[queue.peek()];
if(queue.peek()==0){
queue.poll();
}
for(int i=0;i<sum.length-1;i++){
int max = sum[queue.peek()];
int cur = max - sum[i];
if(cur>res){
res=cur;
}
if(queue.peek()==i+1){
queue.poll();
}
}
return res;
}
public static void main(String[] args) {
int array[]={1,-2,3,10,-4,7,2,-5};
int max = new FindGreatestSumOfSubArray().FindGreatestSumOfSubArray(array);
System.out.println(max);
}
}
//保存窗口最大值的特殊队列
class MaxSumQueue{
LinkedList<Integer> queue = new LinkedList<>();
int sum[];
public MaxSumQueue(int[] sum){
this.sum=sum;
}
public void add(int index){
while(true){
if(queue.isEmpty()){
queue.addLast(index);//下标入队
return;
}else{
if(sum[queue.peekLast()]>sum[index]){//比较的是值
queue.addLast(index);//下标入队
return;
}
}
queue.pollLast();
}
}
public int peek(){
if(queue.isEmpty()){
throw new RuntimeException("队列为空");
}
return queue.peekFirst();
}
public int poll(){
if(queue.isEmpty()){
throw new RuntimeException("队列为空");
}
return queue.pollFirst();
}
}
【java-算法】连续数组最大和
最新推荐文章于 2022-08-23 02:58:13 发布