LeetCode--Greedy

621. Task Scheduler(任務調度)

Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks.Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.
However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.
You need to return the least number of intervals the CPU will take to finish all the given tasks.

Example

Input: tasks = [‘A’,’A’,’A’,’B’,’B’,’B’], n = 2
Output: 8
Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.

Note:

The number of tasks is in the range [1, 10000].
The integer n is in the range [0, 100].

解析:

仔細分析這道題,發現結果和任務的名字無關,只與任務的數量有關。
本題很明顯可以使用貪心策略+優先隊列
任務優先級按照任務數量從大到小進行排列。
每次從優先隊列中選擇優先級最高的任務執行,然後將其從隊列中彈出,如果該任務的實例數量大於1,則將實例數量減1並暫存在一個臨時list中,循環這個步驟直至任務冷卻時間n過去,然後將list中的任務重新加入優先隊列。按照上述步驟,循環,直到任務隊列和臨時list爲空,表示所有任務執行完畢。

c++代碼實現:

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        int m = tasks.size();
        if(m<=1)    return m;
        vector<int> dict(26,0);
        for(char c : tasks)
            dict[c-'A']++;
        priority_queue<int,vector<int>,decltype(std::less<int>())> task_queue;  //從大到小
        for(int i=0; i<26; i++) {
            if(dict[i]!=0)
                task_queue.push(dict[i]);  
        }

        int t = 0;
        while(!task_queue.empty()) {
            int i = 0;
            vector<int> temp;
            while(i<=n) {       //冷卻時間
                if(!task_queue.empty()) {
                    int task = task_queue.top();
                    task_queue.pop();
                    if(task > 1)
                        temp.push_back(task-1); 
                }
                t++;
                if(task_queue.empty() && temp.size()==0)
                    break;
                i++;
            }
            for(int a : temp)      //經過冷卻時間後,將任務重新加入隊列
                task_queue.push(a);     
        }
        return t;
    }
};

402. Remove K Digits

Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.

Note:

The length of num is less than 10002 and will be ≥ k.
The given num does not contain any leading zero.

Example

(1) Input: num = “1432219”, k = 3
Output: “1219”
Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
(2) Input: num = “10200”, k = 1
Output: “200”
Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
(3) Input: num = “10”, k = 2
Output: “0”
Explanation: Remove all the digits from the number and it is left with nothing which is 0.

解析:

貪心法。removeKdigits(num, k) = removeKdigits(removeKdigits(num, 1), k-1)。每次從頭開始找一位進行刪除,進行K輪。
那麼,選擇哪一位進行刪除呢?
(1)如果第2位是0,則刪掉第1個數,會使得整個數量級下降2級。比如:10111–》111;
(2)否則,選擇第一個下降的拐點,刪除這個數,會使得數最小。比如:123546–》12346(刪掉1位的情況下,刪除5是最優選擇)。

C++代碼實現:

class Solution {
public:
    string removeKdigits(string num, int k) {
        int n = 0;
        while(true){
            n = num.size();
            if(n==0 || n<=k)    return "0";
            if(k--==0)  return num;
            if(num[1]=='0') {          //第二位是0,則刪掉第一個可以減少兩個數量級
                int start = 1;
                while( start < n && num[start]=='0')
                    start++;                //找0之後的第一個非0數
                num = num.substr(start);
            }else {        //找到下降的點
                int start = 0;
                while(start < n-1 && num[start] <= num[start+1])    
                    start++;
                num = num.substr(0,start) + num.substr(start+1);
            }
        }
    }
};
發佈了31 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章