「程式碼隨想錄演算法訓練營」第二十六天 | 貪心演算法 part4

云雀AC了一整天發表於2024-08-01

452. 用最少數量的箭引爆氣球

題目連結:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
題目難度:中等
文章講解:https://programmercarl.com/0452.用最少數量的箭引爆氣球.html
影片講解:https://www.bilibili.com/video/BV1SA41167xe
題目狀態:有點思路,但是沒透過,靠ChatGPT透過

思路:

首先看一下題目的大致意思,如下圖:

image

首先要透過氣球的終點來進行排序,然後初始化箭的個數為1,因為至少會有一支箭,之後判斷下一個氣球的開頭位置是否小於前一個氣球的結尾,若大於,則箭的個數要加1,直到遍歷結束。

程式碼:

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if (points.empty()) return 0;
        
        // Sort the points based on the end position of the balloons
        sort(points.begin(), points.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[1] < b[1];
        });
        
        int res = 1; // At least one arrow is needed
        int end = points[0][1];
        
        for (int i = 1; i < points.size(); i++) {
            // If the current balloon starts after the end of the previous balloon
            if (points[i][0] > end) {
                res++;
                end = points[i][1];
            }
        }
        
        return res;
    }
};

435. 無重疊區間

題目連結:https://leetcode.cn/problems/non-overlapping-intervals/
題目難度:中等
文章講解:https://programmercarl.com/0435.無重疊區間.html
影片講解:https://www.bilibili.com/video/BV1A14y1c7E1
題目狀態:看題解

思路:

首先根據每個區間的末尾位置來排序,若末尾的位置比下一個區間的開頭要小,則說明這兩個區間沒有重疊,記錄一下無重疊區間的個數,然後繼續遍歷,直到遍歷結束,返回有重疊的個數。

程式碼:

class Solution {
public:
    // 按照區間右邊界排序
    static bool cmp (const vector<int>& a, const vector<int>& b) {
        return a[1] < b[1];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.size() == 0) return 0;
        sort(intervals.begin(), intervals.end(), cmp);
        int count = 1; // 記錄非交叉區間的個數
        int end = intervals[0][1]; // 記錄區間分割點
        for (int i = 1; i < intervals.size(); i++) {
            if (end <= intervals[i][0]) {
                end = intervals[i][1];
                count++;
            }
        }
        return intervals.size() - count;
    }
};

763. 劃分字母區間

題目連結:https://leetcode.cn/problems/partition-labels/
題目難度:中等
文章講解:https://programmercarl.com/0763.劃分字母區間.html
影片講解:https://www.bilibili.com/video/BV18G4y1K7d5
題目狀態:看題解

思路:

記錄每一個字元的最遠出現位置,然後定義一個區間,遍歷在該區間中的字元最遠出現的位置,若最後遍歷到的位置正好為其區間中所含字元的最遠位置,說明找到了該區間,更新下一個區間的開頭為當前區間的下一個位置,繼續遍歷。

程式碼:

class Solution {
public:
    vector<int> partitionLabels(string S) {
        int hash[27] = {0}; // i為字元,hash[i]為字元出現的最後位置
        for (int i = 0; i < S.size(); i++) { // 統計每一個字元最後出現的位置
            hash[S[i] - 'a'] = i;
        }
        vector<int> result;
        int left = 0;
        int right = 0;
        for (int i = 0; i < S.size(); i++) {
            right = max(right, hash[S[i] - 'a']); // 找到字元出現的最遠邊界
            if (i == right) {
                result.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return result;
    }
};

相關文章