有N个小朋友站在一排,每个小朋友都有一个评分
你现在要按以下的规则给孩子们分糖果:
- 每个小朋友至少要分得一颗糖果
- 分数高的小朋友要他比旁边得分低的小朋友分得的糖果多
你最少要分发多少颗糖果?
class Solution { public: int candy(vector<int> &ratings) { //题意:N个孩子站成一排,每个孩子分配一个分值。给这些孩子派发糖果,满足如下要求: //每个孩子至少一个 //分值更高的孩子比他的相邻位的孩子获得更多的糖果 //求至少分发多少糖果? int len=ratings.size(); if(len==1) return 1; int sum=0; vector<int> v(len,1);//初始将每个孩子的糖果数都设为1 //从左向右扫描,保证一个方向上分数更大的糖果更多 for(int i=1;i<len;i++){ if(ratings[i] > ratings[i-1]) v[i]=v[i-1]+1; } //从右向左扫描,保证另一个方向上分数更大的糖果更多 for(int i=len-2;i>=0;i--){ if(ratings[i] > ratings[i+1] && v[i] <= v[i+1]) v[i]=v[i+1]+1; } for(int i=0;i<len;i++){ sum+=v[i]; } return sum; } };
class Solution { public: /* 遍历两边,首先每个人得一块糖,第一遍从左到右,若当前点比前一个点高就比前者多一块。 这样保证了在一个方向上满足了要求。第二遍从右往左,若左右两点,左侧高于右侧,但 左侧的糖果数不多于右侧,则左侧糖果数等于右侧糖果数+1,这就保证了另一个方向上满足要求 */ int candy(vector<int> &ratings) { int n = ratings.size(); if(n==0) return 0; vector<int> candy(n,1); for(int i=1;i<n;i++) { if(ratings[i] > ratings[i-1]) candy[i] = candy[i-1]+1; } for(int i=n-1;i>=0;i--) { if(ratings[i-1] > ratings[i] && candy[i-1] <= candy[i]) candy[i-1] = candy[i]+1; } return accumulate(candy.begin(),candy.end(),0); } };
正向一次 反向一次ok了
class Solution {
public:
int candy(vector<int> &ratings) {
int n = ratings.size();
int *dp = new int[n], sum = 0;
for(int i=0;i<n;i++) dp[i] = 1;
for(int i=1;i<n;i++)
if(ratings[i] > ratings[i-1])
dp[i] = dp[i-1] + 1;
for(int i=n-1;i>0;i--)
if(ratings[i-1] > ratings[i] && dp[i-1] <= dp[i])
dp[i-1] = dp[i] + 1;
for(int i=0;i<n;i++) sum += dp[i];
return sum;
}
};
import java.util.*; public class Solution { public int candy(int[] ratings) { if(ratings==null || ratings.length==0) { return 0; } int[] count = new int[ratings.length]; //每个孩子初始都有一个糖果 Arrays.fill(count,1); int sum = 0; for(int i=1;i<ratings.length;i++) { if(ratings[i]>ratings[i-1]) { count[i] = count[i-1]+1; } } for(int i=ratings.length-1;i>0;i--) { sum+=count[i]; if(ratings[i]<ratings[i-1] && count[i]>=count[i-1]) { count[i-1] = count[i]+1; } } sum+=count[0]; return sum; } }
import java.util.Arrays; public class Solution { //状态转移方程为 candies[i] = max{candies[i-1], candies[i+1]} + 1 public int candy(int[] ratings) { int sum = 0; int [] candies = new int [ratings.length]; Arrays.fill(candies, 1);//把糖果数组初始化为1 //从左向右使得当ratings[i] > ratings[i-1]时,candies[i] > candies[i-1] for(int i = 1; i < ratings.length; i++) { if(ratings[i] > ratings[i-1]) candies[i] = Math.max(candies[i], candies[i-1] + 1); } //从右向左扫描,使得ratings[i] > ratings[i+1]时,candies[i] > candies[i+1] sum += candies[candies.length-1]; for(int i = ratings.length-2; i >= 0; i--) { if(ratings[i] > ratings[i+1]) candies[i] = Math.max(candies[i], candies[i+1] + 1); sum += candies[i]; } return sum; } }
(1)笨方法
动态规划思想(易于理解):每个糖果的值都要受限与邻居结点(如果评估值比邻居结点大,那么得到的糖果也比邻居结点多)
int candy(vector<int> &ratings) {
vector<vector<int>> v(2,vector<int>());
for(int i = 0;i < ratings.size();i++){
v[0].push_back(0);
v[1].push_back(0);
}
//初始化,每个孩子一个糖果
for(int i = 0;i < ratings.size();i++)
v[0][i] = 1;
bool bc = true;
bool inturn = true;
int pre,pos;
for(int i = 1;i < ratings.size();i++){
if(!bc) break;
bc = false;
//轮流切换两行
if(inturn){
pre = 0;
pos = 1;
inturn = false;
} else{
pre = 1;
pos = 0;
inturn = true;
}
//与左邻居和右邻居比较
for(int j = 0;j < ratings.size();j++){
v[pos][j] = v[pre][j];
if(j>0){
if(ratings[j] > ratings[j-1]){
if(v[pre][j] <= v[pos][j-1]){
v[pos][j] = v[pos][j-1] + 1;
if(!bc) bc = true;
}
}
}
if(j<ratings.size()-1){
if(ratings[j] > ratings[j+1]){
if(v[pos][j] <= v[pre][j+1]){
v[pos][j] = v[pre][j+1] + 1;
if(!bc) bc = true;
}
}
}
}
}
int minCan = 0;
if(inturn) pos = 0;
else pos = 1;
for(int i = 0;i < ratings.size();i++)
minCan += v[pos][i];
return minCan;
}
(2)灵活方法
第一次从左向右扫描找到一个方向上的最大值,第二次从右向左扫描找到另一个方向的最大值。
int candy(vector<int> &ratings) {
int n = ratings.size();
vector<int> v(n,1);
for( int i = 1;i < n;i++)
if(ratings[i]>ratings[i-1]) v[i] = v[i-1]+1;
int sum = 0;
for( int i = n-1;i > 0;i--){
if(ratings[i-1]>ratings[i]&&v[i-1]<=v[i]) v[i-1] = v[i] + 1;
sum += v[i];
}
sum += v[0];
return sum;
}
同步博客 class Solution { public: int candy(vector<int> &ratings) { int r=ratings.size(); map<int,int> mp;mp.clear(); for(int i=0;i<r;i++) mp[i]=1; for(int i=0;i<r-1;i++){ if(ratings[i]<ratings[i+1]) mp[i+1]=mp[i]+1; } int ans=0; for(int i=r-2;i>=0;i--) if(ratings[i]>ratings[i+1]) mp[i]=max(mp[i],mp[i+1]+1); for(int i=0;i<r;i++) ans+=mp[i]; return ans; } };
class Solution { public: int candy(vector<int> &ratings) { queue<int> q; vector<int> G[100000]; int ans=0,r=ratings.size(),indeg[100000],dp[100000]; memset(indeg,0,sizeof(indeg)); memset(dp,0,sizeof(dp)); for(int i=0;i<r-1;i++){ if(ratings[i]>ratings[i+1]) indeg[i]++,G[i+1].push_back(i); else if(ratings[i]<ratings[i+1]) indeg[i+1]++,G[i].push_back(i+1); } for(int i=0;i<r;i++) if(!indeg[i]) dp[i]=1,q.push(i); while(q.size()){ int u=q.front();q.pop(); for(int j=0;j<G[u].size();j++){ int v=G[u][j]; dp[v]=max(dp[v],dp[u]+1); indeg[v]--; if(!indeg[v]) q.push(v); } } for(int i=0;i<r;i++) ans+=dp[i]; return ans; } };
先从左到右,再从右到左扫描两遍即可 public class Solution { public int candy(int[] ratings) { if(ratings == null || ratings.length <= 1) return 1; int[] candy = new int[ratings.length]; int sum = 0; for(int i = 0; i < candy.length; i++) candy[i] = 1; for(int i = 1; i < candy.length; i++){ if(ratings[i] > ratings[i - 1]) candy[i] = candy[i - 1] + 1; } for(int i = candy.length - 1; i > 0; i--){ if(ratings[i] < ratings[i - 1] && candy[i] >= candy[i - 1]) candy[i - 1] = candy[i] + 1; } for(int i = 0; i < candy.length; i++) sum += candy[i]; return sum; } }
class Solution { public: /** * * @param ratings int整型vector * @return int整型 */ int candy(vector<int>& ratings) { // write code here int res = 1, pointer = 0, tmp=1, count =0; for (int i=1; i!=ratings.size(); ++i){ if (ratings[i]>ratings[i-1]){ pointer = i; //指针 if (count != 0) tmp = 1; tmp++; //tmp用于存储当前指针所指向的小朋友分到的糖果数量 res += tmp; count =0; } else if(ratings[i]==ratings[i-1]){ pointer = i; tmp=1; res += tmp; count =0; } else{ res += i-pointer+1; //分数下降,则不移动指针,给指针到当前小朋友每人加一颗糖 count ++; if (tmp>count) res --; } } return res; } };
public class Solution { public int candy(int[] ratings) { if(ratings == null || ratings.length==0) return 0; int[] dp = new int[ratings.length]; dp[0] = 1; // dp[i]存储的是第i个孩子得到的糖果 for(int i=1; i<ratings.length; i++) { if(ratings[i] > ratings[i-1]) { dp[i] = dp[i-1]+1; continue; } if(ratings[i] == ratings[i-1]) { dp[i] = 1; continue; } dp[i] = 1; if (dp[i] < dp[i-1]) { continue; } for(int j=i-1; j>=0; j--) { if (ratings[j]==ratings[j+1]) break; if (ratings[j]>ratings[j+1]&&dp[j]>dp[j+1]) break; if (ratings[j]<ratings[j+1]&&dp[j]<dp[j+1]) break; dp[j]+=1; } } int result = 0; for(int a:dp) result+=a; return result; } }
public class Solution { public int candy(int[] ratings) { if (ratings == null || ratings.length == 0) return 0; int len = ratings.length, dp[] = new int[len], count = len; for (int i = 1; i < len; ++i) { if (ratings[i] > ratings[i - 1]) { dp[i] = dp[i - 1] + 1; } else if (ratings[i] < ratings[i - 1]) { int j = i; while (j > 0 && ratings[j] < ratings[j - 1] && dp[j] >= dp[j - 1]) dp[j - 1] = dp[j--] + 1; } } for (int i = 0; i < len; ++i) count += dp[i]; return count; } }
class Solution { public: int candy(vector<int> &ratings) { int n = ratings.size(); vector<int> res(n,1); for(int i = 0; i < n; i++){ if(ratings[i+1] > ratings[i]){ res[i+1] = res[i] + 1; } } for(int i = n-1; i >=1; i--){ if(ratings[i-1] > ratings[i] && res[i-1] <= res[i]){ res[i-1] = res[i] + 1; } } int sum = 0; for(int i = 0; i < n; i++){ sum += res[i]; } return sum; } };
class Solution { public: int candy(vector<int> &ratings) { int l = ratings.size(); if(l == 1) return 1; int s = 0; vector<int> a(l,1); for(int i=1;i<l;i++) if(ratings[i] > ratings[i-1]) a[i] = a[i-1] + 1; for(int i=l-2;i>=0;i--) if(ratings[i] > ratings[i+1] && a[i] <= a[i+1]) a[i] = a[i+1] + 1; for(int i=0;i<l;i++) s += a[i]; return s; } };
class Solution { public: int candy(vector<int> &ratings) { int n = ratings.size(); int dp[n]; dp[0] = 1; for (int i = 1; i < n; i++) { if (ratings[i] > ratings[i - 1]) { dp[i] = dp[i - 1] + 1; } else { dp[i] = 1; } } for (int i = n - 2; i >= 0; i--) { if (ratings[i] > ratings[i + 1]) { dp[i] = max(dp[i], dp[i + 1] + 1); } } int sum = 0; for (int i = 0; i < n; i++) { sum += dp[i]; } return sum; } };
class Solution { public: int candy(vector<int> &ratings) { vector<pair<int, int>> v; for (int i = 0; i < ratings.size(); ++i) v.push_back({ ratings[i], i }); sort(v.begin(), v.end(), [](const pair<int, int> &a, const pair<int, int> &b) {return a.first < b.first;}); vector<int> candies(ratings.size(), 0); int n_count = 0; for (auto e : v) { int i = e.second; int left = 0; if (i - 1 >= 0) left = candies[i - 1]; int right = 0; if (i + 1 < candies.size()) right = candies[i + 1]; candies[i] = 1; if (left != 0 && ratings[i - 1] < ratings[i]) candies[i] = left + 1; if (right != 0 && ratings[i + 1] < ratings[i]) candies[i] = max(candies[i], right + 1); n_count += candies[i]; } return n_count; } };
import java.util.*; public class Solution { public int candy(int[] ratings) { int[] arr1 = new int[ratings.length]; int[] arr2 = new int[ratings.length]; Arrays.fill(arr1, 1); Arrays.fill(arr2, 1); for (int i = 1; i < ratings.length; i ++) { if(ratings[i] > ratings[i - 1]) arr1[i] = arr1[i - 1] + 1; } for (int i = ratings.length - 1; i >= 1; i --) { if(ratings[i] < ratings[i - 1]) arr2[i - 1] = arr2[i] + 1; } int sum = 0; for (int i = 0; i < ratings.length; i ++) { sum += arr1[i] > arr2[i] ? arr1[i] : arr2[i]; } return sum; } }
class Solution { public: int candy(vector<int>& ratings) { int ret = 0; int len = ratings.size(); vector<int> temp(len, 1); for(int i = 1; i < len; i++){ if(ratings[i] > ratings[i-1]){ temp[i] = temp[i-1]+1; } } for(int i = len-2; i >= 0; i--){ if(ratings[i] > ratings[i+1]){ temp[i] = max(temp[i], temp[i+1]+1); } } for(int i = 0; i < len; i++){ ret += temp[i]; } return ret; } };
class Solution { public: int candy(vector<int> &ratings) { int n=ratings.size(); if(n==0) return 0; vector<int> res(n);//存每个小孩应发的糖果数 res[0]=1; for(int i=1;i<n;i++){//不断遍历ratings并更新res //如果新加入的小孩大于前一个小孩,则糖果比前一个小孩+1 if(ratings[i]>ratings[i-1]) { res[i]=res[i-1]+1; } //关键:如果等于前一个小孩,则新小孩只需要分一个糖果,res不需要更新 else if(ratings[i]==ratings[i-1]) { res[i]=1; } //如果小于前一个小孩,则新加入小孩分一个糖果,之前的小孩应该比他多分到糖果 else{ res[i]=1; //如果前面的小孩只有一个糖果,需要更新res if(res[i-1]==1) { //前面的小孩都多分一个糖果,直到递增结束 int j=i-1; for(;j!=0&&res[j]<res[j-1];j--){ res[j]++; } //关键:注意相等rating的情况 if(res[j]<=res[j+1] && ratings[j]!=ratings[j+1])res[j]++; } } } int sum=0; for(auto e:res){ sum+=e; } return sum; } };