题目地址:https://oj.leetcode.com/problems/candy/
题意:有一羣小孩排成一列,给他们发糖,保证每个人至少一个糖而且每个小孩得到的糖一定比 “与他相邻的且身高低于他”(如果有的话)的小孩得到的糖多,求最少发多少糖。
trick:两个相邻的小孩如果身高相等的话就忽略掉这两个小孩之间的比较。连续身高相等的小孩,除了处于波峯或者波谷的,都只发一颗糖是最优解的子集。
思路:这道题想了好几种方法都WA了,最后参考了网上的答案,发现这道题我以前做过。。。
波谷的小孩只发一颗糖也是最优解的子集,正序和倒序各扫一般(有方向),遇到波谷就给这个小孩发一个糖,在波谷到波峯路径上的小孩得到的糖递增一个。
最后,这里的处于波峯的小孩由于要满足左右两边的条件限制,所以得到的糖应该是左扫描和右扫描中的最大值。
技巧:先将数组头尾个插入一个身高接近无限大的小孩,这样原来的第一个小孩和最后一个小孩就不用特殊判断了。
#include <vector>
#include<iostream>
#define INF 0x7fffffff
using namespace std;
class Solution {
public:
int candy(vector<int> &ratings) {
ratings.insert(ratings.begin(),INF);
ratings.push_back(INF);
int size = ratings.size();
if(size == 1) return 1;
vector<int> tmp (size,1);//记录发糖数,初始化全为1
for(int i=1; i<size-1; ++i){
int j =size-1-i;
int now1=ratings[i],now2=ratings[j];
//正序扫一遍
if(ratings[i-1]<now1 && now1<=ratings[i+1]){
tmp[i] = tmp[i-1]+1;
}
else if(ratings[i-1]<now1 && now1>ratings[i+1]){
tmp[i] = max(tmp[i-1]+1,tmp[i]);
}
//倒序扫一遍
if(ratings[j+1]<now2 && now2<=ratings[j-1]){
tmp[j] = tmp[j+1]+1;
}
else if(ratings[j+1]<now2 && now2>ratings[j-1]){
tmp[j] = max(tmp[j+1]+1,tmp[j]);
}
}
int ans=0;
for(int i=1; i<size-1; ++i){
ans+=tmp[i];
}
//cout<<ans<<endl;
return ans;
}
};