1.452. 用最少数量的箭引爆气球 - 力扣(LeetCode)
思路:这道题运用双指针,如果left>right,就计数。
贪心题目有时候就是这样,看起来很简单,思路很直接,但是一写代码就感觉贼复杂无从下手。这里其实是需要代码功底的,那代码功底怎么练?多看多写多总结
static bool cmp(vector<int> &a, vector<int> &b)
{
return a[0] < b[0];
}
int findMinArrowShots(vector<vector<int>> &points)
{
sort(points.begin(), points.end(), cmp);
int result = 0;
int left = 0;
int right = 0;
for (int i = 0; i < points.size(); i++)
{
if (i == 0){
result++;
left = points[i][0];
right = points[i][1];
continue;
}
left = points[i][0];
right = min(points[i][1], right);
if (left > right)
{
result++;
right = points[i][1];
}
}
return result;
}
思路:本题大幅使用贪心算法。其实重叠算法就是说:已有的右边界与新的边界的左边界相比,如果没有重叠,就更新right,否则(发生重叠),right = min(right,intervals[i][1]),取最小其实还是贪心。当然最开始要对数组进行排序。
static bool cmp(const vector<int> &a, const vector<int> &b)
{
if (a[0] != b[0])
{
return a[0] < b[0];
}
else
{
return a[1] < b[1];
}
}
int eraseOverlapIntervals(vector<vector<int>> &intervals)
{
int num = 0;
sort(intervals.begin(), intervals.end(), cmp);
int right = intervals[0][1];
for (int i = 1; i < intervals.size(); i++)
{
if(intervals[i][0] < right){//有重叠
num++;
right = min(right, intervals[i][1]);
}else{
right = intervals[i][1];
}
}
return num;
}
这道贪心我是有思路的,也就是说首先统计每个元素的最远到达的地方。但是后面找到分割点的时候由于代码水平受限.....没有写出来。下面我就多写一下找分割点的思路吧:
首先遍历整个字符串s,设置左右指针,右指针是为了找到之后与索引做差,从而或者分割点之间的距离的。而right = max(right,hash[s[i]-'a']),然后逐步遍历,一直通过hash与right最比较,直到i==right,那么就返回。
vector<int> partitionLabels(string s)
{
// 统计每个字母出现最远的位置
int hash[27] = {0};
for (int i = 0; i < s.size(); i++)
{
hash[s[i] - 'a'] = i;
}
vector<int> result;
int right = 0;
int left = 0;
for (int i = 0; i < s.size(); i++)
{
right = max(right, hash[s[i] - 'a']);
if (i == right)
{
result.push_back(i - left + 1);
left = i + 1;
}
}
return result;
}