leetcode502. IPO

題目要求

Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects.java

You are given several projects. For each projecti, it has a pure profit Pi and a minimum capital of Ci is needed to start the corresponding project. Initially, you have W capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.算法

To sum up, pick a list of at most k distinct projects from given projects to maximize your final capital, and output your final maximized capital.api

Example 1: 數據結構

Input: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].ide

Output: 4操作系統

Explanation: Since your initial capital is 0, you can only start the project indexed 0.
After finishing it you will obtain profit 1 and your capital becomes 1.
With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.
Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.線程

Note:code

  1. You may assume all numbers in the input are non-negative integers.
  2. The length of Profits array and Capital array will not exceed 50,000.
  3. The answer is guaranteed to fit in a 32-bit signed integer.

假設如今團隊最多可以完成k個項目,每一個項目分別被標記了所須要投入的資本capital和最後生成的純利潤profit,已知團隊初始時有W的初始資金,問按照什麼順序完成項目從而獲得最大的利潤,返回最終團隊的資金數量。排序

思路和代碼

這個其實和操做系統中針對現成死鎖預測的銀行家算法很像。銀行家算法的就在於嘗試分配當前的資源給多個須要該資源的線程,若是可以找到一個發放序列成功的知足全部線程的要求,則說明不會致使死鎖。而這裏也是一樣,爲了達到最大的效益,這意味着每次都要用有限的資原本得到最高的利潤。所以咱們要選擇合適的數據結構,使得咱們先快速篩選出可以投資的全部項目,再選擇一個利潤最高的項目進行執行。隊列

代碼中有兩種實現方式,一種是利用兩個優先隊列,一個優先隊列用於將隊列中的項目按照所需資金從小到大進行排序,而另外一個優先隊列則用於將隊列中的項目按照得到利潤從大到小進行排序。現將全部的項目假如資金優先隊列中,並取出當前全部能夠執行的項目放入利潤優先隊列中,此時利潤優先隊列中取出來的第一個項目就是利潤最高的可執行項目。按照這個執行順序繼續執行,直到完成了要求的K個項目。

public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {  
    PriorityQueue<Integer> capitalQueue = new PriorityQueue<>(Comparator.comparingInt(o -> Capital[o]));  
    PriorityQueue<Integer> profitQueue = new PriorityQueue<>((o1, o2) -> Profits[o2] - Profits[o1\]);  
  
    IntStream.range(0, Capital.length).forEach(capitalQueue::offer);  
  
    while (k-- != 0) {  
        while (!capitalQueue.isEmpty() &&  Capital[capitalQueue.peek()] <= W) {  
            profitQueue.offer(capitalQueue.poll());  
        }  
        if (profitQueue.isEmpty()) {  
            break;  
        }  
        W += Profits[profitQueue.poll()];  
    }  
    return W;  
}

還有一種方式就是對全部的項目先按照利潤排序,再按照資本排序。這樣從優先隊列中順序選出的第一個可以完成的項目就是當前完成的最優項目。這裏須要把當前不能完成的項目放回優先隊列。

public int findMaximizedCapital2(int k, int W, int[] Profits, int[] Capital) {  
    int length = Profits.length;  
    k = Math.min(k, length);  
    PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>(){  
        @Override  
  public int compare(int[] a, int[] b) {  
            int p = b[0] - a[0];  
            if (p == 0) return a[1] - b[1];  
            return p;  
        }  
    });  
  
    for (int i = 0; i < length; i++) pq.add(new int[] {Profits[i], Capital[i]});  
    for (int i = 0; i < k; i++) {  
        List<int[]> scanned = new ArrayList<>();  
        int mark = pq.size();  
        while (pq.size() > 0) {  
            int[] check = pq.poll();  
            if (check[1] <= W) {  
                W += check[0];  
                break;  
            } else {  
                scanned.add(check);  
            }  
        }  
        if (scanned.size() == mark) break;  
        pq.addAll(scanned);  
    }  
  
    return W;  
}
相關文章
相關標籤/搜索