代碼隨想錄算法訓練營|第三十八天|435. 无重叠区间、763.划分字母区间、56. 合并区间。刷题心得(c++)

本文围绕LeetCode的435.无重叠区间、763.划分字母区间、56.合并区间三道题展开。作者分享了自己看到题目的初始想法和看完代码随想录后的感悟,详细阐述了各题的实现思路,包括错误思路及原因、正确思路,还给出代码示例。最后总结了实现中遇到的困难及学习收获。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

讀題

435. 无重叠区间

自己看到题目的第一想法

看完代码随想录之后的想法

763.划分字母区间

自己看到题目的第一想法

看完代码随想录之后的想法

56. 合并区间

自己看到题目的第一想法

看完代码随想录之后的想法

435. 无重叠区间 - 實作

思路

錯誤思路

正確思路

Code

錯誤代碼

正確代碼

763.划分字母区间 - 實作

思路

Code

56. 合并区间 - 實作

思路

錯誤思路

正確思路

Code

錯誤代碼

正確代碼

總結

自己实现过程中遇到哪些困难

今日收获,记录一下自己的学习时长

相關資料


讀題

435. 无重叠区间

自己看到题目的第一想法

這題整體感覺是跟射氣球那題大致相同,只是這一次不是要找重疊的部分,而是透過不重疊的部分將數組remove ,先根據左邊界排序,如果當前區間跟上一個區間有重合的部分,那就不++ 持續向後迭代

看完代码随想录之后的想法

思路有想出來,但是代碼實作上出現了問題,區間問題的思路難度不高,但是很考驗自己對於思路轉為實作的代碼能力。

763.划分字母区间

自己看到题目的第一想法

我看不懂題目想要的是什麼,光看題目反而不知道要做什麼,這題直接看題解

看完代码随想录之后的想法

看完後,才知道要求的是當下元素組的全部區間,看完卡哥講解以及整體代碼,發現代碼很直覺,但是思路如果沒有搞清楚,根本不可能找到這個切入點,還需要多練練。

56. 合并区间

自己看到题目的第一想法

這題在sort 的時侯,應該就要sort兩個部分

如果兩個左邊界相同的話排序右邊界,

如果下一個右邊界小於目前的右邊界目前右邊界不動

如果是右邊界大於但左邊界小於則更新右邊界為下一個數值的右邊界

看完代码随想录之后的想法

思路對了,但做法錯了,直接在intervals數組當中進行操作,導致代碼變得複雜,看完隨想錄之後,才知道可以透過操作results數組來對區間進行合併,學到了。

435. 无重叠区间 - 實作

思路

錯誤思路

  1. 排序intervals
  2. 比較右邊界是否大於左邊界,如果大於代表有重疊results++,如果沒有,更新比較位置至當前節點。

錯誤點:

  1. 更新索引的策略:當判斷當前區間(由索引**j指定)與下一個區間(由索引i指定)重疊時,沒有更新j**的值。意味著在下一次迭代中,仍然在比較舊的區間與新的區間是否重疊,而不是比較最近保留的區間與新的區間是否重疊。
  2. 選擇保留的區間:當有多個區間與當前區間重疊時,沒有選擇一個結束時間最早的區間來保留。

正確思路

  1. 排序intervals
  2. 比較上一個的右邊界是否大於當前左邊界,如果大於代表有重疊results++,並更新當前的右邊界,取最小值。取右邊界最小值,等同於擦掉右邊界的最大值,避免有過多的重疊區間出現。

Code

錯誤代碼

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0]) return a[1] < b[1];
        return a[0] < b[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(),cmp);
        int result = 0;
        int j = 0;
        for(int i = 1; i < intervals.size(); i++) {
            if(intervals[j][1] > intervals[i][0]) {
                result++;
            } else {
                j = i;
            }
        }
        return result;
    }
};

正確代碼

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0]) return a[1] < b[1];
        return a[0] < b[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(),cmp);
        int result = 0;
        int j = 0;
        for(int i = 1; i < intervals.size(); i++) {
            if(intervals[i][0] < intervals[i - 1][1]) {
                result++;
                intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]); 
            }
        }

        return result;
    }
};

763.划分字母区间 - 實作

思路

  1. 建立hash陣列紀錄每個字母的最長距離
  2. 建立左右指針,紀錄區間
  3. 遍歷s字串,紀錄s字串每個字母的最長距離。
  4. 遍例s字串
    1. 比較當前的right字串與當前字母的最遠距離,哪個最遠
    2. 如果當前位置等於right,代表前面區間已包含所有該區間存在的字母,將當前區間放入results,並更新left。
  5. return results.

Code

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int hash[27] = {0};
        vector<int> results;
        int left = 0, right = 0;
        for(int i = 0; i < s.size(); i++) {
            hash[s[i]-'a'] = i;
        }
        for(int i = 0; i < s.size(); i++) {
            right = max(right, hash[s[i] - 'a']);
            if(i == right) {
                results.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return results;

    }
};

56. 合并区间 - 實作

思路

錯誤思路

  1. 假設intervals.size小於2 直接return
  2. 排序intervals
  3. 如果當前的左邊界小於上一個的右邊界,更新interval的左邊界取最小,右邊界取最大
  4. 如果大於等於上一個的右邊界,將上一個interval放入results數組當中
  5. 結束後處理最後一個點

錯誤點: 直接在intervals數組中進行操作,因為數組的數量是不斷在變化的,所以會導致代碼非常複雜,雖然整體思路是對的,但代碼底子不好,導致問題產生。

正確思路

  1. 假設intervals.size小於2 直接return
  2. 排序intervals
  3. 建立results數組
  4. 將第一個intervals加入到results數組當中
  5. 如果當前的左邊界小於等於esults數組最後的右邊界,更新results右邊界取最大。
  6. 如果大於則將當前的interval加入到results數組當中
  7. return results數組。

Code

錯誤代碼

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0]) return a[1] < b[1];
        return a[0] < b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.size() < 2) return intervals;
        sort(intervals.begin(), intervals.end(),cmp);
        vector<vector<int>> results;
        for(int i = 1; i < intervals.size(); i++) {
            if(intervals[i][0] < intervals[i - 1][1]) {
                intervals[i][1] = max(intervals[i - 1][1], intervals[i][1]); 
                intervals[i][0] = min(intervals[i - 1][0], intervals[i][0]); 
            } else {
                results.push_back(intervals[i - 1]);
            }
        }
        if(intervals[intervals.size() - 1][0] <= results[results.size() - 1][1]) {
                results[results.size() - 1][1] = max(results[results.size() - 1][1], intervals[intervals.size() - 1][1]); 
                results[results.size() - 1][0] = min(results[results.size() - 1][0], intervals[intervals.size() - 1][0]); 
        } else {
            results.push_back(intervals[intervals.size() - 1]);
        }

        return results;
    }
};

正確代碼

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0]) return a[1] < b[1];
        return a[0] < b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.size() < 2) return intervals;
        sort(intervals.begin(), intervals.end(),cmp);
        vector<vector<int>> results;
        results.push_back(intervals[0]);
        for(int i = 1; i < intervals.size(); i++) {
            if(intervals[i][0] <= results.back()[1]) {
                results.back()[1] = max(results.back()[1], intervals[i][1]);
            } else {
                results.push_back(intervals[i]);
            }
        }

        return results;
    }
};

總結

自己实现过程中遇到哪些困难

今天整體而言思路不難,除了第二題一開始看不懂題意,第一題跟第三題跟昨天寫的題目很像,所以困難點主要是自己的代碼實作能力的不足,只能一步步去彌補這部分的差距。

今日收获,记录一下自己的学习时长

今天大概學了2hr,整體而言對於貪心算法的實作有了更深一層的了解,思路有漸漸被打開的感覺。

相關資料

  1. 无重叠区间

https://programmercarl.com/0435.无重叠区间.html

763.划分字母区间

https://programmercarl.com/0763.划分字母区间.html

  1. 合并区间

https://programmercarl.com/0056.合并区间.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值