前缀和(解决超时)

LightItUP(时间复杂度估算例题)

在这里插入图片描述
计算机一秒只能运算1e8次,本题中时间限制其他语言2秒,由于Java跑的慢,理论上是2e8,但是当作1e8次。

第一版代码:run time out

import java.util.ArrayList;
import java.util.Scanner;

public class lightItUp {
    public static void main(String[] args) {
        Scanner sc= new Scanner(System.in);
        ArrayList<Integer> timesFirst= new ArrayList<>();
        int n=sc.nextInt();
        int last= sc.nextInt();
        timesFirst.add(0);
        for (int i=0;i<n;i++){
            timesFirst.add(sc.nextInt());
        }
        timesFirst.add(last);

        //计算初始开灯时间
        int first=0;
        for (int i=0;i<timesFirst.size()-1;i+=2){
            first=first+timesFirst.get(i+1)-timesFirst.get(i);
        }

        int insert=0;
        for (int i=1;i<timesFirst.size();i++){
            ArrayList<Integer> times= (ArrayList<Integer>) timesFirst.clone();
            if (i%2!=0){
                if (times.get(i)-1!=times.get(i-1)){
                    times.add(i,times.get(i)-1);
                }else continue;
            }else {
                if (times.get(i-1)+1!=times.get(i)){
                    times.add(i,times.get(i-1)+1);
                }else continue;
            }

            for (int j=0;j<times.size()-1;j+=2){
                insert=insert+times.get(j+1)-times.get(j);
            }

            if (insert>first){
                first= insert;
                insert=0;
            }
            else {
                insert=0;
                continue;
            }
        }
        System.out.println(first);
    }
}

题中1≤n≤1e5, 2 < M <1e9,由于本题中存在双重for循环,故时间复杂度为O(n^2) ,即:时间复杂度估算:1e10

前缀和

前缀和数组:
在这里插入图片描述

用法:用于储存好原有数组,从而需要时调用。

例如:以下代码计算奇数前缀和

//计算奇数前缀和
HashMap<Integer,Integer>jishu= new HashMap<>();
int temp= 0;
for (int i=0;i<timesFirst.size()-1;i+=2){
    if (i==0){
        jishu.put(0,timesFirst.get(1));
    }else {
        temp=timesFirst.get(i+1)-timesFirst.get(i);
        jishu.put(i,jishu.get(i-2)+temp);
    }
}

后缀和


        //计算偶数后缀和
        HashMap<Integer,Integer>oushu= new HashMap<>();
        if (timesFirst.size()%2==0){
            for (int i=timesFirst.size()-2;i>0;i-=2){
                if (i==timesFirst.size()-2){
                    oushu.put(timesFirst.size()-3,timesFirst.get(timesFirst.size()-2)-timesFirst.get(timesFirst.size()-3));
                }else {
                    temp=timesFirst.get(i)-timesFirst.get(i-1);
                    oushu.put(i-1,oushu.get(i+1)+temp);
                }
            }
        }
        else{
            for (int i=timesFirst.size()-1;i>0;i-=2){
                if (i==timesFirst.size()-1){
                    oushu.put(timesFirst.size()-2,timesFirst.get(timesFirst.size()-1)-timesFirst.get(timesFirst.size()-2));
//                    System.out.println("偶数中:i"+(timesFirst.size()-2)+"value:"+(timesFirst.get(timesFirst.size()-1)-timesFirst.get(timesFirst.size()-2)));
                }else {
                    temp=timesFirst.get(i)-timesFirst.get(i-1);
                    oushu.put(i-1,oushu.get(i+1)+temp);
//                    System.out.println("偶数中:i:"+(i-1)+"temp:"+temp);
                }
            }
        }

题解

首先,预处理一个奇数前缀和、偶数后缀和

第二版AC

package niuke;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class lightItUp {
    public static void main(String[] args) {
        Scanner sc= new Scanner(System.in);
        ArrayList<Integer> timesFirst= new ArrayList<>();
        int n=sc.nextInt();
        int last= sc.nextInt();
        timesFirst.add(0);
        for (int i=0;i<n;i++){
            timesFirst.add(sc.nextInt());
        }timesFirst.add(last);

        //计算初始开灯时间
        int first=0;
        for (int i=0;i<timesFirst.size()-1;i+=2){
            first=first+timesFirst.get(i+1)-timesFirst.get(i);
        }

        //计算奇数前缀和
        HashMap<Integer,Integer>jishu= new HashMap<>();
        int temp= 0;
        for (int i=0;i<timesFirst.size()-1;i+=2){
            if (i==0){
                jishu.put(0,timesFirst.get(1));
            }else {
                temp=timesFirst.get(i+1)-timesFirst.get(i);
                jishu.put(i,jishu.get(i-2)+temp);
            }
        }

        //计算偶数后缀和
        HashMap<Integer,Integer>oushu= new HashMap<>();
        if (timesFirst.size()%2==0){
            for (int i=timesFirst.size()-2;i>0;i-=2){
                if (i==timesFirst.size()-2){
                    oushu.put(timesFirst.size()-3,timesFirst.get(timesFirst.size()-2)-timesFirst.get(timesFirst.size()-3));
                }else {
                    temp=timesFirst.get(i)-timesFirst.get(i-1);
                    oushu.put(i-1,oushu.get(i+1)+temp);
                }
            }
        }
        else{
            for (int i=timesFirst.size()-1;i>0;i-=2){
                if (i==timesFirst.size()-1){
                    oushu.put(timesFirst.size()-2,timesFirst.get(timesFirst.size()-1)-timesFirst.get(timesFirst.size()-2));
//                    System.out.println("偶数中:i"+(timesFirst.size()-2)+"value:"+(timesFirst.get(timesFirst.size()-1)-timesFirst.get(timesFirst.size()-2)));
                }else {
                    temp=timesFirst.get(i)-timesFirst.get(i-1);
                    oushu.put(i-1,oushu.get(i+1)+temp);
//                    System.out.println("偶数中:i:"+(i-1)+"temp:"+temp);
                }
            }
        }

//        for (int i=0;i<timesFirst.size();i++){
//            System.out.print("奇数:i:"+i+"value:"+jishu.get(i));
//            System.out.println("偶数:i:"+i+"value:"+oushu.get(i));
//        }

        //测试插入
        int insert=0;
        for(int i=1;i<timesFirst.size();i++){
            if (timesFirst.size()==2){
                break;
            }
            if (timesFirst.size()==3){
                insert=jishu.get(0)-1+oushu.get(1);
                first=Math.max(insert,first);
                break;
            }
            else {
                if (i==1){
                    insert=jishu.get(0)-1+oushu.get(1);
                    first=Math.max(insert,first);
                    continue;
                }

                else {
                    if (i%2==0){
                        if (i==timesFirst.size()-1){
                            insert=jishu.get(i-2);
                            first=Math.max(insert,first);
                            continue;
                        }
                        insert=jishu.get(i-2)+oushu.get(i-1)-1;
                        first=Math.max(insert,first);
                        continue;
                    }else {
                        if (i==timesFirst.size()-1){
                            insert=jishu.get(i-1);
                            first=Math.max(insert,first);
                            continue;
                        }
                        insert=jishu.get(i-1)+oushu.get(i)-1;
                        first=Math.max(insert,first);
                        continue;
                    }
                }
            }
        }

        System.out.println(first);


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值