要想分出最少的糖果,利用贪心思想,肯定是相邻位置没有增加的情况下,大家都分到1,相邻位置有增加的情况下,分到糖果数加1就好。什么情况下会增加糖果,相邻位置有得分差异,可能是递增可能是递减,如果是递增的话,糖果依次加1,如果是递减糖果依次减1?这不符合最小,因为减到最后一个递减的位置可能不是1,必须从1开始加才是最小,那我们可以从最后一个递减的位置往前反向加1
class Solution {
public:
int candy(vector<int>& arr) {
//记录每个位置的糖果数,初始为1
vector<int> nums(arr.size(), 1);
//从左到右遍历
for(int i = 1; i < arr.size(); i++){
//如果右边在递增,每次增加一个
if(arr[i] > arr[i - 1])
nums[i] = nums[i - 1] + 1;
}
//记录总糖果数
int res = nums[arr.size() - 1];
//从右到左遍历
for(int i = arr.size() - 2; i >= 0; i--){
//如果左边更大但是糖果数更小
if(arr[i] > arr[i + 1] && nums[i] <= nums[i + 1])
nums[i] = nums[i + 1] + 1;
//累加和
res += nums[i];
}
return res;
}
};
时间复杂度:O(n),单独遍历两次
空间复杂度:O(n),记录每个位置糖果数的辅助数组
我们利用贪心思想,什么时候需要的主持人最少?那肯定是所有的区间没有重叠,每个区间首和上一个的区间尾都没有相交的情况,我们就可以让同一位主持人不辞辛劳,一直主持了。但是题目肯定不是这种理想的情况,那我们需要对交叉部分,判断需要增加多少位主持人。
class Solution {
public:
int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
vector<int> start;
vector<int> end;
//分别得到活动起始时间
for(int i = 0; i < n; i++){
start.push_back(startEnd[i][0]);
end.push_back(startEnd[i][1]);
}
//分别对开始和结束时间排序
sort(start.begin(), start.end());
sort(end.begin(), end.end());
int res = 0;
int j = 0;
for(int i = 0; i < n; i++){
//新开始的节目大于上一轮结束的时间,主持人不变
if(start[i] >= end[j])
j++;
else
//主持人增加
res++;
}
return res;
}
};
时间复杂度:O(n
log
2
\log_2
log2n)遍历都是O(n),sort排序为O(n
log
2
\log_2
log2n)
空间复杂度:O(n),辅助空间记录开始时间和结束时间的数组
class Solution {
public:
//优先比较开始时间,再比较结束时间
static bool comp(vector<int>& a, vector<int>& b){
if(a[0] == b[0])
return a[1] < b[1];
else
return a[0] < b[0];
}
int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
sort(startEnd.begin(), startEnd.end(), comp);
//小顶堆
priority_queue<int, vector<int>, greater<int> > q;
//可能有负区间
q.push(INT_MIN);
for(int i = 0; i < n; i++){
//最近的活动结束时间小于当前活动开始时间
if(q.top() <= startEnd[i][0])
q.pop();
q.push(startEnd[i][1]);
}
//剩余的活动等于主持人数
return q.size();
}
};
时间复杂度:O(n
log
2
\log_2
log2n),sort排序是O(n
log
2
\log_2
log2n),一次遍历,循环中维护堆每次O(n
log
2
\log_2
log2n)
空间复杂度:O(n),堆大小最大为n