淘先锋技术网

首页 1 2 3 4 5 6 7

1. 题目描述

假设 力扣(LeetCode)即将开始 IPO 。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。

给你 n 个项目。对于每个项目 i ,它都有一个纯利润 profits[i] ,和启动该项目需要的最小资本 capital[i]

最初,你的资本为 w 。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。

总而言之,从给定项目中选择 最多 k 个不同项目的列表,以 最大化最终资本 ,并输出最终可获得的最多资本。

答案保证在 32 位有符号整数范围内。

示例 1:

输入:k = 2, w = 0, profits = [1,2,3], capital = [0,1,1]
输出:4
解释:
由于你的初始资本为 0,你仅可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。

示例 2:

输入:k = 3, w = 0, profits = [1,2,3], capital = [0,1,2]
输出:6

提示:

1 <= k <= 1 0 5 10^5 105
0 <= w <= 1 0 9 10^9 109
n == profits.length
n == capital.length
1 <= n <= 1 0 5 10^5 105
0 <= profits[i] <= 1 0 4 10^4 104
0 <= capital[i] <= 1 0 9 10^9 109


来源:力扣(LeetCode)
链接:
https://leetcode-cn.com/problems/ipo


2. 解答

2.1 朴素求解

也就是直接提取题意,按照题意,需要进行k轮,每次我们去寻找满足capital[i]<=w 且 profits[i]最大的那个下标,也就是我们下一轮的目标。代码如下:

class Solution {
    public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
        boolean[] used = new boolean[capital.length];
        int sum = w;
        for (int i = 0; i < k; i++) { // choose k step
            int idx = getMaxProfitIdx(capital, profits, used, w);
            if(idx == -1) return sum;
            used[idx] = true;
            w += profits[idx];
            sum += profits[idx];
        }
        return sum;
    }

    // 获取可选择的最大利润
    private int getMaxProfitIdx(int[] capital, int[] profits, boolean[] used, int w) {
        int maxProfits = Integer.MIN_VALUE;
        int idx = -1;
        for (int i = 0; i < capital.length; i++) {
            if(used[i] || (idx != -1 && capital[i] == capital[idx] && profits[i] == profits[idx])) continue;
            if(capital[i] <= w && maxProfits < profits[i]){
                maxProfits = profits[i];
                idx = i;
            }
        }
        return idx;
    }
}

在这里插入图片描述

不出意外超时了。

其实可以预料,因为数组的长度为 1 0 5 10^5 105,那么对于一个时间复杂度为 O ( n 2 ) O(n^2) O(n2)的算法来说是通不过的。这一点需要强化记忆。

2.2 堆排序

因为我们每次是找寻满足条件的最大利润,故而可以使用堆排序来做。

class Solution {
    public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
        int len = capital.length;
        boolean[] used = new boolean[len];
        int[][] pairs = new int[len][2];
        for (int i = 0; i < len; i++) {
            pairs[i][0] = profits[i];
            pairs[i][1] = capital[i];
        }
        Arrays.sort(pairs, (o1, o2) -> o1[1] - o2[1]);
        PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1);
        int curIdx = 0;
        for (int i = 0; i < k; i++) { // choose k step
            while(curIdx < len && pairs[curIdx][1] <= w){
                queue.add(pairs[curIdx][0]);
                curIdx++;
            }
            if(!queue.isEmpty()){
                w += queue.poll();
            }else break;
        }
        return w;
    }
}

在这里插入图片描述


Thanks