406 根据身高重建队列 1.同分发糖果对比,依旧存在两条比较链路,一是身高比较,二是前面有多少个较高人比较 2.使用sort函数时要注意设计比较器 3.不能两种比较因素同时考虑,应当先选择一个进行排序满足,达成局部最优,然后接着处理第二个比较条件,从局部最优达成全局最优
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>> reconstructQueue(vector<vector<int>>& people) {
sort (people.begin(), people.end(), cmp);
list<vector<int>> que; // list底层是链表实现,插入效率比vector高的多
for (int i = 0; i < people.size(); i++) {
int position = people[i][1]; // 插入到下标为position的位置
std::list<vector<int>>::iterator it = que.begin();
while (position--) { // 寻找在插入位置
it++;
}
que.insert(it, people[i]);
}
return vector<vector<int>>(que.begin(), que.end());
}
};
- 用最少数量箭引爆气球 1.理解此处的局部最优!!!通过不断更新右边界达到局部最优条件 2.学会设计比较器
class Solution {
public:
//设计比较器
static bool cmp(const vector<int>& a,const vector<int>& b){
return a[0]<b[0];
}
int findMinArrowShots(vector<vector<int>>& points) {
//排除特殊情况
if(points.size()==0) return 0;
//对气球进行排序
sort(points.begin(),points.end(),cmp);
//设计arrow存储箭的数量
int arrow=1;//必有第一个气球
for(int i=1;i<points.size();i++){//从第二个球开始
if(points[i][0]>points[i-1][1]){//前一个气球的右边界小于当前气球的左边界
arrow++;
}
else{
points[i][1]=min(points[i][1],points[i-1][1]);//更新局部的气球右边界
}
}
return arrow;
}
};
435.无重叠区间 1.本题类似最少数量箭射爆气球,首先要对区间按照边界进行排序,根据选择的边界设计比较器 2.本题的局部最优依然是不断更新右边界,当不重叠时,更新为最新的右边界并计数。
class Solution {
public:
//设计比较器
static bool cmp(vector<int>& a,vector<int>& b){
return a[1]<b[1];//使用右边界排序
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if(intervals.size()<=1) 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
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;
}
};