算法-可完成的最大任务数

一解析:

为了尽可能多的完成任务,充分利用时间,越早越好,所以从项目开启的那一天起就开始做任务,一直做到项目结束为止。

但是,对于第i天来说,若可执行的任务有多个,该如何选择?根据设定,这些任务都有各自的结束时间,所以为了尽可能多的做任务,优先选择结束时间早的任务;若第i天没有任务,就选择等待(休息)。

根据思路,可写出暴力搜索的代码(超时)

java 复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int[][] task=new int[n][2];
        int minTime=Integer.MAX_VALUE,maxTime=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            task[i][0]=in.nextInt();
            task[i][1]=in.nextInt();
            minTime=Math.min(minTime,task[i][0]);
            maxTime=Math.max(maxTime,task[i][1]);
        }
        int ans=0;
        // 避免重复执行
        int[] used=new int[n];
        while(minTime<=maxTime){
            int minEnd=Integer.MAX_VALUE,index=-1;
            for(int i=0;i<n;i++){
                int[] arr=task[i];
                //可执行的任务中选择结束时间最早的
                if(used[i]==0&&arr[0]<=minTime&&minTime<=arr[1]){
                    if(arr[1]<minEnd){
                        minEnd=arr[1];
                        index=i;
                    }
                }
            }
            if(index!=-1){
                used[index]=1;
                ans++;

            }
            minTime++;
        }
        System.out.println(ans);
    }
}

二、优化:

根据暴力枚举,不难得出正确答案。但是时间复杂度为O(n2),显然会超时。

1:任务数组排序

第i天可执行的任务,其开始时间都小于等于i,若把任务数组按照开始时间进行升序排序,则在寻找可执行任务时,可避免全表扫描(任务的开始时间超过i时,停止搜索)。

2:扫描结果复用

对于第i天可执行的任务,可收集起来,供第i+1天复用,避免再重复扫描判断这些任务。为方便起见,用队列收集第i天可执行的任务,为筛选最早结束的任务,队列存储任务的结束时间,按小顶堆排序。

细节:对于第i天收集的到可执行任务队列,由于队列是复用的,所以可能包含第i天之前收集的任务,这些任务可能过期(根据任务结束时间<i判断),需要清理。

3:代码

java 复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int[][] task=new int[n][2];
        int minTime=Integer.MAX_VALUE,maxTime=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            task[i][0]=in.nextInt();
            task[i][1]=in.nextInt();
            maxTime=Math.max(maxTime,task[i][1]);
            minTime=Math.min(minTime,task[i][0]);
        }
        Arrays.sort(task,(a,b)->a[0]-b[0]);

        int ans=0,i=0;
        PriorityQueue<Integer> queue=new PriorityQueue<>((a,b)->a-b);
        while(minTime<=maxTime){
            while(i<n&&task[i][0]<=minTime){
                queue.add(task[i][1]);
                i++; 
            }
            //queue是可复用的,所以queue中的有些任务是之前添加的,可能过期,需要清理
            while(!queue.isEmpty()&&queue.peek()<minTime){
                queue.poll();
            }
            // 堆顶即被选中的任务
            if(!queue.isEmpty()){
                queue.poll();
                ans++;
            }
            minTime++;
        }
        System.out.println(ans);

    }
}

优化后,最多访问一遍任务数组,所以时间复杂度变成O(max{n,m}),n为任务数,m为任务最大结束时间

相关推荐
达文汐2 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗2 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子2 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
培风图南以星河揽胜3 分钟前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
算法_小学生4 分钟前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2594 分钟前
力扣hot100 - 234、回文链表
算法·leetcode·链表
Gorgous—l6 分钟前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
熬夜造bug6 分钟前
LeetCode Hot100 刷题路线(Python版)
算法·leetcode·职场和发展
启山智软26 分钟前
【中大企业选择源码部署商城系统】
java·spring·商城开发
2401_8384725129 分钟前
C++中的访问者模式
开发语言·c++·算法