一群孩子做游戏,现在请你根据游戏得分来发糖果,要求如下:
1. 每个孩子不管得分多少,起码分到一个糖果。
2. 任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果。(若相同则无此限制)
给定一个数组
代表得分数组,请返回最少需要多少糖果。
要求: 时间复杂度为
空间复杂度为
数据范围:
,
[1,1,2]
4
最优分配方案为1,1,2
[1,1,1]
3
最优分配方案是1,1,1
public class Solution {
/**
* 给定一个数组 arrarr 代表得分数组,请返回最少需要多少糖果。
*
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
int candy[] = new int[arr.length];
for (int i = 0; i < candy.length; i++) {
candy[i] = 1;
}
for (int i = 1; i < arr.length; i++) {
if (arr[i] > arr[i - 1]) {
candy[i] = candy[i - 1] + 1;
}
}
int count = 0 ;
for (int i = arr.length - 1; i > 0; i--) {
if (arr[i - 1] > arr[i] && candy[i - 1] <= candy[i]) {
candy[i - 1] = candy[i] + 1;
}
count += candy[i];
}
return count += candy[0];
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
// 参考代码随想录
public int candy (int[] arr) {
// write code here
int len = arr.length;
int res = 0;
int[] preMin = new int[len];
int[] sufMin = new int[len];
Arrays.fill(preMin, 1);
Arrays.fill(sufMin, 1);
for (int i = 1; i < len; i++) if (arr[i] > arr[i - 1]) preMin[i] = preMin[i-1] + 1;
for (int i = len - 2; i >= 0; i--) if (arr[i] > arr[i + 1]) sufMin[i] = sufMin[i+1] + 1;
for (int i = 0; i < len; i++) res += Math.max(preMin[i], sufMin[i]);
return res;
}
} public static int candy(int[] arr) {
// write code here
int[] temp = new int[arr.length];
Arrays.fill(temp, 1);
for (int t = 0; t < arr.length; t++) {
if ((t + 1) <= arr.length - 1 && arr[t + 1] > arr[t])
getCandy(arr, temp, t + 1);
}
for (int t = arr.length - 1; t >= 0; t--) {
if ((t - 1) >= 0 && arr[t - 1] > arr[t])
getCandy2(arr, temp, t - 1);
}
for (int i = 0, j = i + 1, k = i + 2; k < temp.length; i++, j++, k++) {
if (temp[j] - temp[i] > 1 && temp[j] - temp[k] > 1) {
if (temp[i] > temp[k]) {
temp[j] = temp[i] + 1;
} else {
temp[j] = temp[k] + 1;
}
}
}
int ret = 0;
for (int num : temp) {
ret += num;
}
System.out.println(Arrays.toString(temp));
return ret;
}
private static void getCandy(int[] arr, int[] temp, int t) {
temp[t]++;
if ((t + 1) <= arr.length - 1 && arr[t + 1] > arr[t])
getCandy(arr, temp, t + 1);
}
private static void getCandy2(int[] arr, int[] temp, int t) {
temp[t]++;
if ((t - 1) >= 0 && arr[t - 1] > arr[t])
getCandy2(arr, temp, t - 1);
} public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// 左遍历一次,再右遍历一次
if(arr.length<=1) return 1;
int[] nums=new int[arr.length];//辅助数组,初始化为1
for(int i=0;i<nums.length;i++){
nums[i]=1;
}
//左遍历 i-1,i
for(int i=1;i<arr.length;i++){//i从1开始
if(arr[i]>arr[i-1]){ //如果原数组递增,那就给num[i]糖果+1
nums[i]=nums[i-1]+1;
}
}
int ans=nums[arr.length-1];
//右遍历 i,i+1
for(int i=arr.length-2;i>=0;i--){
if(arr[i]>arr[i+1]&&nums[i]<=nums[i+1]){
nums[i]=nums[i+1]+1;
}
ans=ans+nums[i];//ans原来是个空数组 使用了两次辅助数组nums[i]
}
return ans;
} import java.util.*;
public class Solution {
/**
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// write code here
int[] scores = new int[arr.length];
int cd = 0;
for (int i = 0; i < arr.length ; i++) {
scores[i] = 1;
}
for (int i = arr.length - 1 ; i > 0; i--) {
if (arr[i] < arr[i - 1]) {
scores[i - 1] = scores[i] + 1;
}
}
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] < arr[i + 1] && scores[i+1] <= scores[i]) {
scores[i + 1] = scores[i] + 1;
}
}
for (int i = 0; i < arr.length; i++) {
cd += scores[i];
System.out.println(scores[i]);
}
return cd;
}
} import java.util.*;
public class Solution {
public int candy (int[] arr) {
// write code here
int n = arr.length;
int[] left = new int[n];
int[] right = new int[n];
for (int i = 1; i < n; i++) {
//左侧单调递增区间
if (arr[i] > arr[i - 1]) left[i] = left[i - 1] + 1;
}
for (int i = n - 2; i >= 0; i--) {
//右侧单调递减区间
if (arr[i] > arr[i + 1]) right[i] = right[i + 1] + 1;
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans += Math.max(left[i], right[i]) + 1;
}
return ans;
}
} import java.util.*;
public class Solution {
/**
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// write code here
int[] res = new int[arr.length];
for(int i=0;i<arr.length;i++) res[i] = 1;
for(int i=1;i<arr.length;i++){
// if(arr[i] - arr[i-1]==0) res[i] = res[i-1];
if(arr[i] - arr[i-1]>0) res[i] = res[i-1] + 1;
}
for(int i=arr.length-2;i>=0;i--){
int temp = 0;
// if(arr[i] - arr[i+1]==0) temp = res[i+1];
if(arr[i] - arr[i+1]>0) temp = res[i+1] + 1;
res[i] = Math.max(res[i],temp);
}
int sum = 0;
for(int x:res) sum+=x;
return sum;
}
} import java.util.*;
public class Solution {
/**
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// write code here
int[] left=new int[arr.length];
int[] right=new int[arr.length];
int candy=0;
left[0]=1;
right[arr.length-1]=1;
for(int i=1;i<=arr.length-1;i++){
if(arr[i]>arr[i-1]){
left[i]=left[i-1]+1;
}else{
left[i]=1;
}
}
for(int i=arr.length-2;i>=0;i--){
if(arr[i]>arr[i+1]){
right[i]=right[i+1]+1;
}else{
right[i]=1;
}
}
for(int i=0;i<=arr.length-1;i++){
candy=candy+Math.max(left[i],right[i]);
}
return candy;
}
} import java.util.*;
public class Solution {
/**
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// write code here
int[] dp = new int[arr.length];
Arrays.fill(dp, 1);
int res = 0;
for (int i = 1; i < arr.length; i ++) {
if (arr[i] > arr[i - 1]) dp[i] = dp[i - 1] + 1;
}
res = dp[arr.length - 1];
for (int i = arr.length - 2; i >= 0; i--) {
if (arr[i] > arr[i + 1] && dp[i] <= dp[i + 1]) dp[i] = dp[i + 1] + 1;
res += dp[i];
}
return res;
}
} 题解: 要想分出最少的糖果,利用贪心思想,肯定是相邻位置没有增加的情况下,大家都分到1,相邻位置有增加的情况下,分到糖果数加1就好。 什么情况下会增加糖果,相邻位置有得分差异,可能是递增可能是递减,如果是递增的话,糖果依次加1,如果是递减糖果依次减1? 最后不符合最小,原因是序列中的两个任意两个元素之间必然是递增,递减,相等等三种情况,不管多长的序列都可以细分成任意两个元素的子问题 想象序列前半部分递增,后半部分递减,如果后半部分比前半部分短,最后减完是不是最后一个元素是不是大于1,所以不能得到最小值 如果是多个递增递减的序列的组合形成的序列,那么其中任意两个不等长子序列都会产生这个情况,所以诞生了下面的思路: 1.先从左到右,大于的就+1,小于的不管,然后从后向前遍历,前面的大于后面的就+1,假设序列只有递增递减两部分,如1232或者12321或者2321 12321肯定直接适用,前者因为3处于返回的时候的递增,所以应该更新为1个糖果+1=2,但是这样就把当时原来递增的数量给破坏了,所以由于前后子序列的不确定性 我们直接取max(原来的递增时数量,递减返回时的后置元素+1),谁大取谁,因为这样一定能满足大于两边的情况import java.util.*; public class Solution { /** * pick candy * @param arr int整型一维数组 the array * @return int整型 */ public int candy (int[] arr) { int length = arr.length; int count = 0; int num[] = new int[length]; Arrays.fill(num,1); for(int i=1;i<length;i++){ if(arr[i]>arr[i-1]){ num[i] = num[i-1]+1; } } for(int i = length-1;i>0;i--){ if(arr[i]<arr[i-1]){ num[i-1] = Math.max(num[i-1],num[i]+1); } } for(int i :num){ count+=i; } return count; } }
public class Solution {
public int candy (int[] arr) {
if (arr==null || arr.length==0) return 0;
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
++res[i];
if (i>0 && arr[i]>arr[i-1]) {
res[i] = res[i-1]+1;
}
}
int sum = 0;
for (int i = arr.length-1; i >=0 ; i--) {
if (i<arr.length-1 && arr[i]>arr[i+1] && res[i]<=res[i+1]) {
res[i] = res[i+1]+1;
}
sum = sum + res[i];
}
return sum;
}
} 思路(贪心策略):
注意:若两个孩子得分相同,分配糖果无限制,即不需要保证分数相同(相邻与否),得到的糖果数相同
1、先创建一个长度为arr.length,元素都为1的数组
2、从左往右看:索引值从 0 到length-2,看arr[i] 与 arr[i+1]的关系,如果arr[i]<arr[i+1],则 i+1位置 上的糖果比 i位置 多给一个,即candy[i+1]=candy[i]+1;
3、从右往左看:索引值从 length-1 到 1,看arr[i] 与 arr[i-1]的关系,如果arr[i-1]>arr[i],则 i-1位置 上的糖果要保证比 i位置 上的多,即candy[i-1]=Math.max(candy[i-1],candy[i]+1); 因为candy[i-1]可能已经在“从左往右看”的时候被再次赋值过,这个值有可能比candy[i]大,因此需要进行比较,选出最大的,这样可以保证糖果比左右的都要多,例如:分数序列123451,5就比1+1大
总结:从左往右,保证右边比左边大的时候,糖果数也大;从右往左,保证右边比左边大或相等的情况下,糖果数符合要求
import java.util.*;
public class Solution {
public int candy (int[] arr) {
// write code here
int len = arr.length;
if(len==0) return 0;
if(len==1) return 1;
int[] candy = new int[len];
for(int i=0;i<len;i++){
candy[i]=1;
}
for(int i=1;i<len;i++){
if(arr[i]>arr[i-1]){
candy[i]=candy[i-1]+1;
}
}
for(int i=len-1;i>0;i--){
if(arr[i-1]>arr[i]){
candy[i-1] = Math.max(candy[i-1],candy[i]+1);
}
}
int res=0;
for(int i=0;i<len;i++){
res+=candy[i];
}
return res;
}
}
import java.util.*;
public class Solution {
/**
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
public int candy (int[] arr) {
// write code here
if(arr.length == 1)return 1;
int[] candy = new int[arr.length];
candy[0] = 1;
for(int i = 1; i < arr.length; i++){
candy[i] = 1;
if(arr[i] > arr[i - 1]){
candy[i] = candy[i - 1] + 1;
}
}
int res = candy[arr.length - 1];
for(int i = arr.length - 2; i >= 0; i--){
if(arr[i] > arr[i + 1]){
candy[i] = Math.max(candy[i], candy[i + 1] + 1);
}
res += candy[i];
}
return res;
}
} import java.util.*;
public class Solution {
public int candy (int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int n = arr.length;
int[] nums = new int[n];
// 先分一个
Arrays.fill(nums, 1);
// 得分比前一个多,需要保证糖果数量也比前一个多
for (int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
nums[i] = nums[i - 1] + 1;
}
}
// 得分比后一个多,需要保证糖果数量也比后一个多
for (int i = n - 2; i >= 0; i--) {
if (arr[i] > arr[i + 1]) {
if (nums[i] <= nums[i + 1]) {
nums[i] = nums[i + 1] + 1;
}
}
}
int sum = 0;
for (int num:nums) {
sum += num;
}
return sum;
}
}