[Leetcode] Greedy

来源:互联网 发布:山西九鼎软件怎么样 编辑:程序博客网 时间:2024/06/16 15:39

[Leetcode] Greedy

502 IPO

Description

Analysis

This problem can be easily described as we need to find the most profitable projects with the ability to afford the necessary capital. The problem can be solved by using the two-layer loop, but it will take too much time so we need to optimize. Just thinking about the two-layer, in each second-layer loop, we need to find the available projects and the most profitable projects. But the thing can be simplified. We can store the available projects in a priority queue sorted by profits and another priority queue to store the unavailable projects sorted by capital. Then whenever we get more capital, we can check and append projects from the priority queue which stores the unavailable projects.

What’s necessary to mention is the syntax of a priority queue. We need to implement a class which implements an override function, operator(). And that’s all about it.

code

class ComparisonInt {public:    bool operator() (int a, int b) {        return a < b;    }};class ComparisonVec {public:    bool operator() (pair<int, int> a, pair<int, int> b) {        return a.first > b.first;    }};class Solution {public:    int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {        priority_queue<int, vector<int>, ComparisonInt> ProfitsQueue;        priority_queue<pair<int, int>, vector<pair<int, int>>, ComparisonVec> CapProQueue;        for (int i = 0; i < Profits.size(); i++) {            CapProQueue.push(pair<int, int>(Capital[i], Profits[i]));        }        while (k != 0) {            while (!CapProQueue.empty() && CapProQueue.top().first <= W) {                ProfitsQueue.push(CapProQueue.top().second);                CapProQueue.pop();            }            if (ProfitsQueue.empty()) { return W; }            W += ProfitsQueue.top();            ProfitsQueue.pop();            k--;        }        return W;    }};

621.Task Scheduler

Desciption

Analysis

There are two methods for you to solve the question.
The first one is straightforward but it takes a lot more time. We can store the available tasks in a priority queue sorted by the rest of tasks and store the waiting tasks in a priority queue sorted by the waiting time. Then, whenever the available queue has a task, we can pop it out, if the task num is more than 1, then push it into waiting queue, otherwise, drop it out. And each time, we need to manually decrease the necessary waiting time by 1 in the waiting queue. The main idea I want to introduce is I want to give the top priority of the task with the most left task num, because when it wait, the CPU can do other things.

Stary 2017-10-26 at 2.56.18 P

#include <vector>#include <iostream>#include <map>#include <queue>using namespace std;class Solution {public:    int leastInterval(vector<char>& tasks, int n) {        map<char, int> hash;        for (auto each : tasks) {            hash[each]++;        }        priority_queue<int> availableQueue;        queue<pair<int, int>> waitingQueue;        for (auto each : hash) {            availableQueue.push(each.second);        }        int task;        int costed = 0;        int size = 0;        pair<int, int> cur;        while (!waitingQueue.empty() || !availableQueue.empty()) {            task = -1;            if (!availableQueue.empty()) {                task = availableQueue.top();                availableQueue.pop();                task -= 1;            }            size = waitingQueue.size();            for (int i = 0; i < size; i++) {                cur = waitingQueue.front();                waitingQueue.pop();                cur.first -= 1;                if (cur.first == 0 || cur.first == -1) {                    availableQueue.push(cur.second);                } else {                    waitingQueue.push(cur);                }            }            if (task > 0) {                waitingQueue.push(pair<int, int>{n, task});            }            costed++;        }        return costed;    }};int main() {    vector<char> task{'A', 'A', 'A', 'B', 'B', 'B'};    Solution so;    cout << so.leastInterval(task, 2) << endl;    return 0;}

The second one is a bit hard to understand but is efficient. Let’s think about that if the CPU doesn’t have to wait any seconds then the needed time to finish all tasks is the tasks.size(). However, if the CPU has to wait,
then we can construct the interval by letting the tasks in A be finished first and the rest tasks be finished during they wait. Each interval will last N. At last, each task in A can be finished without waiting, so just add it up. A is a series of tasks with the most number of rest of tasks.

Stary 2017-10-26 at 2.59.59 P

class Solution {public:    int leastInterval(vector<char>& tasks, int n) {        unordered_map<char,int>mp;        int count = 0;        for(auto e : tasks)        {            mp[e]++;            count = max(count, mp[e]);        }        int ans = (count-1)*(n+1);        for(auto e : mp) if(e.second == count) ans++;        return max((int)tasks.size(), ans);    }};
原创粉丝点击