【java-算法】连续数组最大和

11 篇文章 0 订阅
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();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值