Skip to content

Latest commit

 

History

History
106 lines (88 loc) · 3.64 KB

502.ipo.md

File metadata and controls

106 lines (88 loc) · 3.64 KB

我们只有 W 的资本,可以做 K 个项目,那么我们肯定要优先选择我们能做的可以获取最大收益的前 K 个项目,很显然这是一个贪心问题

问题是,怎么确定我们能做的 K 个项目呢?

我们想到了优先队列,这个优先队列存储的是每个项目的收益和成本,compare 条件很显然应该是收益大,成本小优先

我们按这个原则出堆的时候,堆顶的项目存在两种情况:

  • 项目启动资金大于我们当前资本:
    • 堆顶的项目虽然收益可能最大,但是受制于项目启动资金,项目不能做,于是我们要继续寻找能产生次大收益的项目;
    • 这些出堆的项目我们暂时保存在一个缓冲区,等待我们做了一个可以做的项目,这时候我们的资本就增加了,可以把缓冲区的项目重新入堆
  • 项目启动资金小于等于我们当前资本:
    • 项目可以做

代码实现:

class Node {
    int p, c;

    public Node(int p, int c) {
        this.p = p;
        this.c = c;
    }
}

class Solution {
    public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
        int n = profits.length;
        PriorityQueue<Node> heap = new PriorityQueue<>(new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                if (o1.p == o2.p) {
                    return o1.c - o2.c; // 小顶
                }
                return o2.p - o1.p; // 大顶
            }
        });

        for (int i = 0; i < n; i++) {
            heap.add(new Node(profits[i], capital[i]));
        }
        while (k-- > 0) {
            List<Node> buf = new ArrayList<>();
            while (!heap.isEmpty()) {
                Node top = heap.poll();
                if (top.c > w) {
                    buf.add(top);
                } else {
                    w += top.p;
                    heap.addAll(buf);
                    if(!buf.isEmpty()) buf.clear();
                    break;
                }
            }
            if (!buf.isEmpty()) return w; // 没有可以做的项目了
        }

        return w;
    }

}

提交后,我们发现上面的代码执行效率比较低,如何优化一下呢?

我们有必要一开始把所有数据都入堆吗,想一下,实际场景中,我们只需要关心我们可以做的项目,不能做的项目我们没必要入堆,我们不能每次都遍历所有项目吧,这样效率会很低,于是我们考虑把按照项目的启动资金从小到大排序,并使用一个游标记录遍历到的成本最小项目索引,优化后的代码如下:

class Solution {

    public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
        int n = profits.length;
        // 按纯利从大到小
        PriorityQueue<Integer> heap = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        int[][] project = new int[n][2];
        for (int i = 0; i < n; i++) {
            project[i][0] = profits[i];
            project[i][1] = capital[i];
        }
        // 按成本从小到大
        Arrays.sort(project, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1] - o2[1];
            }
        });

        for (int i = 0; k-- > 0; ) {
            while (i < n && project[i][1] <= w) {
                heap.add(project[i++][0]);
            }
            if (heap.isEmpty()) return w;
            w += heap.poll();
        }

        return w;
    }

}