目录
讀題
435. 无重叠区间
自己看到题目的第一想法
這題整體感覺是跟射氣球那題大致相同,只是這一次不是要找重疊的部分,而是透過不重疊的部分將數組remove ,先根據左邊界排序,如果當前區間跟上一個區間有重合的部分,那就不++ 持續向後迭代
看完代码随想录之后的想法
思路有想出來,但是代碼實作上出現了問題,區間問題的思路難度不高,但是很考驗自己對於思路轉為實作的代碼能力。
763.划分字母区间
自己看到题目的第一想法
我看不懂題目想要的是什麼,光看題目反而不知道要做什麼,這題直接看題解
看完代码随想录之后的想法
看完後,才知道要求的是當下元素組的全部區間,看完卡哥講解以及整體代碼,發現代碼很直覺,但是思路如果沒有搞清楚,根本不可能找到這個切入點,還需要多練練。
56. 合并区间
自己看到题目的第一想法
這題在sort 的時侯,應該就要sort兩個部分
如果兩個左邊界相同的話排序右邊界,
如果下一個右邊界小於目前的右邊界目前右邊界不動
如果是右邊界大於但左邊界小於則更新右邊界為下一個數值的右邊界
看完代码随想录之后的想法
思路對了,但做法錯了,直接在intervals數組當中進行操作,導致代碼變得複雜,看完隨想錄之後,才知道可以透過操作results數組來對區間進行合併,學到了。
435. 无重叠区间 - 實作
思路
錯誤思路
- 排序intervals
- 比較右邊界是否大於左邊界,如果大於代表有重疊results++,如果沒有,更新比較位置至當前節點。
錯誤點:
- 更新索引的策略:當判斷當前區間(由索引**
j
指定)與下一個區間(由索引i
指定)重疊時,沒有更新j
**的值。意味著在下一次迭代中,仍然在比較舊的區間與新的區間是否重疊,而不是比較最近保留的區間與新的區間是否重疊。 - 選擇保留的區間:當有多個區間與當前區間重疊時,沒有選擇一個結束時間最早的區間來保留。
正確思路
- 排序intervals
- 比較上一個的右邊界是否大於當前左邊界,如果大於代表有重疊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.划分字母区间 - 實作
思路
- 建立hash陣列紀錄每個字母的最長距離
- 建立左右指針,紀錄區間
- 遍歷s字串,紀錄s字串每個字母的最長距離。
- 遍例s字串
- 比較當前的right字串與當前字母的最遠距離,哪個最遠
- 如果當前位置等於right,代表前面區間已包含所有該區間存在的字母,將當前區間放入results,並更新left。
- 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. 合并区间 - 實作
思路
錯誤思路
- 假設intervals.size小於2 直接return
- 排序intervals
- 如果當前的左邊界小於上一個的右邊界,更新interval的左邊界取最小,右邊界取最大
- 如果大於等於上一個的右邊界,將上一個interval放入results數組當中
- 結束後處理最後一個點
錯誤點: 直接在intervals數組中進行操作,因為數組的數量是不斷在變化的,所以會導致代碼非常複雜,雖然整體思路是對的,但代碼底子不好,導致問題產生。
正確思路
- 假設intervals.size小於2 直接return
- 排序intervals
- 建立results數組
- 將第一個intervals加入到results數組當中
- 如果當前的左邊界小於等於esults數組最後的右邊界,更新results右邊界取最大。
- 如果大於則將當前的interval加入到results數組當中
- 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,整體而言對於貪心算法的實作有了更深一層的了解,思路有漸漸被打開的感覺。
相關資料
- 无重叠区间
https://programmercarl.com/0435.无重叠区间.html
763.划分字母区间
https://programmercarl.com/0763.划分字母区间.html
- 合并区间