452 用最少数量的箭引爆气球
如上图所示 我们可以先用每一个气球的左边界来对气球进行一个排序 然后我们就可以开始遍历整个序列 我们看当前气球的左边界是否大于前一个气球的右边界 如果大于 就说明两者不重叠 那么弓箭数就要加1 如果不大于 就说明两者重叠 此时我们应该更新一下重叠气球的最小右边界 也就是取两个气球右边界的最小值(因为可以存在【1,4】 【2,3】这样的情况)
class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){
return a[0] < b[0];
}
public:
int findMinArrowShots(vector<vector<int>>& points) {
if(points.size()==0){
return 0;
}
int ans=1;
sort(points.begin(),points.end(),cmp);
for(int i=1;i<points.size();i++){
if(points[i][0]>points[i-1][1]){
ans++;
}else{
points[i][1]=min(points[i - 1][1], points[i][1]);
}
}
return ans;
}
};
435. 无重叠区间
思路是一样的 如果有重叠区间 就让ans++ 并且将end更新到两个区间的最小值(因为右边界越小 重叠的可能性也就越小 所以我们用end来保存最小的右边界) 表示要删除区间 如果没有重叠 就要end更新到当前区间的右边界
class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){
return a[0]<b[0];
}
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if(intervals.size()<=1){
return 0;
}
sort(intervals.begin(),intervals.end(),cmp);
int ans=0;
int end=intervals[0][1];
for(int i=1;i<intervals.size();i++){
if(intervals[i][0]<end){
ans++;
end=min(end,intervals[i][1]);
}else{
end=intervals[i][1];
}
}
return ans;
}
};
763 划分字母区间
题意如上图所示 如果一个字母区间包含了字母a那么所有a都必须在这个区间里面出现 所以我们先记录下每一个字母出现的最大的下标 然后开始遍历字符串 用left和right表示左右边界并且不断的去更新right右边界 如果i遍历到right的地方 就截取这一区间 然后更新left的值
class Solution {
public:
vector<int> partitionLabels(string s) {
int hash[27]={0};
for(int i=0;i<s.size();i++){
hash[s[i]-'a']=i;
}
vector<int> ans;
int left=0,right=0;
for(int i=0;i<s.size();i++){
right=max(right,hash[s[i]-'a']);
if(i==right){
ans.push_back(right-left+1);
left=i+1;
}
}
return ans;
}
};
56 合并区间
这题思路和前面重叠区间的思路相似 都是先对区间左边进行排序 然后寻找是否有重叠区间 如果重叠就更新右边界 但是这一题的处理技巧不一样 是直接将要处理的区间放入ans数组 然后开始遍历判断当前区间和ans数组里最后的区间作比较 直接修改ans数组里面的区间 如果不重叠的话 就将当前区间放入ans数组
class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){
return a[0]<b[0];
}
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> ans;
sort(intervals.begin(),intervals.end(),cmp);
if(intervals.size()==0){
return ans;
}
ans.push_back(intervals[0]);
for(int i=1;i<intervals.size();i++){
if(intervals[i][0]<=ans.back()[1]){
ans.back()[1]=max(ans.back()[1],intervals[i][1]);
}else{
ans.push_back(intervals[i]);
}
}
return ans;
}
};
738 单调递增的数字
该题要求满足数字是单调递增的 所以很容易想到我们应该从后往前遍历 如果后面的数大于前面的数就不要做处理 如果后面的数小于前面的数 我们就需要把后面的数字变为9 然后前面的数字减1 因为这样是满足让整体最大(但是我们不能直接把后面数字变成9 需要用一个flag来记录从哪里往后需要变成9 因为只要一个位置的数要变成9 那么该位置后面的所有数字变成9是都成立的且是满足最大的 比如100这个例子 如果不标记flag得到的结果是90)
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string snum=to_string(n);
int index=snum.size();
for(int i=snum.size()-1;i>0;i--){
if(snum[i]<snum[i-1]){
index=i;
snum[i-1]--;
}
}
for(int i=index;i<snum.size();i++){
snum[i]='9';
}
return stoi(snum);
}
};