题意整理

  • 有n个工厂,提供了抵达时间和物资数量,由于每天只能装载一天,所以物资数量也相当于停留时间。
  • 按先抵达的工厂先装载的规则,通过k个码头最少多少天完成装载任务。

方法一(排序+小顶堆)

1.解题思路

  • 首先将工厂按抵达时间排好。
  • 然后遍历所有工厂,如果某个工厂已经装载完毕,则从堆中移除。如果正在装载的工厂不足k个,说明还有空余的码头没有使用,直接将抵达时间+消耗时间放到堆里;如果达到k个,则需要等待堆顶的那个工厂装载完,将堆顶时间+消耗时间放到堆里,并且移除堆顶的工厂。
  • 最后取出堆中最大的元素,即是最后一个工厂的装载结束时间。

动图展示:
图片说明

2.代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 
     * @param k int整型 
     * @param a int整型一维数组 
     * @param b int整型一维数组 
     * @return long长整型
     */
    public long solve (int n, int k, int[] a, int[] b) {
        //用于存放工厂id和抵达时间
        int[][] arr=new int[n][2];
        for(int i=0;i<n;i++){
            arr[i][0]=i;
            arr[i][1]=a[i];
        }
        //按抵达时间排序
        Arrays.sort(arr,(o1,o2)->o1[1]-o2[1]);

        //初始化小顶堆
        PriorityQueue<Long> queue=new PriorityQueue<>();
        for(int i=0;i<n;i++){
            int id=arr[i][0];
            //如果某个工厂已经装载完毕,则从堆中移除
            while(!queue.isEmpty()&&a[id]>=queue.peek()){
                queue.poll();
            }
            //如果正在装载的工厂不足k个,则直接将抵达时间+消耗时间放到堆里
            if(queue.size()<k){
                queue.offer((long)a[id]+b[id]);
            }
            //如果达到k个,则需要等待堆顶的那个工厂装载完
            else{
                queue.offer(queue.peek()+b[id]);
                queue.poll();
            }
        }

        //取出堆中最大的元素,即是最后一个工厂的装载结束时间
        while(queue.size()>1){
            queue.poll();
        }
        return queue.peek();

    }
}

3.复杂度分析

  • 时间复杂度:最多n个工厂入堆,每次插入和删除的时间复杂度是,所以最终的时间复杂度是
  • 空间复杂度:需要额外大小为n的小顶堆,所以空间复杂度是

方法二(TreeMap+小顶堆)

1.解题思路

  • 首先初始化小顶堆,并将k个工厂预先放入堆。
  • 然后初始化map,将抵达时间作为key,消耗时间作为value放入map,保证按抵达时间排好
  • 遍历所有工厂,如果抵达时间大于等于某个工厂的结束任务时间,直接将抵达时间+消耗时间入堆;如果小于,则将堆顶时间+消耗时间入堆。
  • 最后取出堆中最大的元素,即是最后一个工厂的装载结束时间。

2.代码实现

import java.util.*;

public class Solution {
    /**
     * 
     * @param n int整型 
     * @param k int整型 
     * @param a int整型一维数组 
     * @param b int整型一维数组 
     * @return long长整型
     */
    public long solve(int n, int k, int[] a, int[] b) {
        //初始化小顶堆,并将k个工厂预先放入堆
        PriorityQueue<Long> queue=new PriorityQueue<>();
        for(int i=0;i<k;i++){
            queue.add(1L);
        }
        //初始化map,将抵达时间作为key,消耗时间作为value放入map
        TreeMap<Integer,Integer> map=new TreeMap<>();
        for(int i=0;i<n;i++){
            map.put(a[i],b[i]);
        }
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){
            Integer day=entry.getKey();
            Integer duration=entry.getValue();
            Long poll=queue.poll();
            //如果抵达时间大于等于某个工厂的结束任务时间,直接将抵达时间+消耗时间入堆
            if(day>=poll){
                queue.add(Long.valueOf(day+duration));
            }
            //如果小于,则将堆顶时间+消耗时间入堆
            else{
                queue.add(poll+duration);
            }
        }
        //取出堆中最大的元素,即是最后一个工厂的装载结束时间
        while(queue.size()>1){
            queue.poll();
        }
        return queue.peek();
    }
}

3.复杂度分析

  • 时间复杂度:最多n个工厂入堆,每次插入和删除的时间复杂度是,所以最终的时间复杂度是
  • 空间复杂度:需要额外大小为n的小顶堆和TreeMap,所以空间复杂度是