1、解题思路
这是一个典型的贪心算法问题,可以通过两次遍历数组来解决:
- 从左到右遍历 :确保每个孩子与其左侧相邻孩子满足糖果分配规则。 如果当前孩子的得分比左侧高,则当前孩子的糖果数至少为左侧孩子的糖果数加1。否则,当前孩子的糖果数至少为1(初始值)。
- 从右到左遍历 :确保每个孩子与其右侧相邻孩子满足糖果分配规则。 如果当前孩子的得分比右侧高,则当前孩子的糖果数至少为右侧孩子的糖果数加1(但不要减少当前已分配的糖果数)。否则,保持当前糖果数不变。
- 求和:将两次遍历后的糖果数取最大值,然后求和。
这种方法确保每个孩子既满足左侧规则又满足右侧规则,同时使用最少糖果。
2、代码实现
C++
#include <vector> class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * pick candy * @param arr int整型vector the array * @return int整型 */ int candy(vector<int>& arr) { // write code here int n = arr.size(); if (n == 0) { return 0; } vector<int> candies(n, 1); // 每个孩子至少 1 个糖果 // 从左到右遍历, 确保比左边高时糖果更多 for (int i = 1; i < n; ++i) { if (arr[i] > arr[i - 1]) { candies[i] = candies[i - 1] + 1; } } // 从右到左遍历, 确保比右边高时糖果更多 for (int i = n - 2; i >= 0; --i) { if (arr[i] > arr[i + 1]) { candies[i] = max(candies[i], candies[i + 1] + 1); } } // 计算糖果总数 int total = 0; for (int num : candies) { total += num; } return total; } };
Java
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * pick candy * @param arr int整型一维数组 the array * @return int整型 */ public int candy (int[] arr) { // write code here int n = arr.length; if (n == 0) return 0; int[] candies = new int[n]; Arrays.fill(candies, 1); // 每个孩子至少1个糖果 // 从左到右遍历,确保比左边高时糖果更多 for (int i = 1; i < n; ++i) { if (arr[i] > arr[i - 1]) { candies[i] = candies[i - 1] + 1; } } // 从右到左遍历,确保比右边高时糖果更多 for (int i = n - 2; i >= 0; --i) { if (arr[i] > arr[i + 1]) { candies[i] = Math.max(candies[i], candies[i + 1] + 1); } } // 计算总糖果数 int total = 0; for (int num : candies) { total += num; } return total; } }
Python
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # pick candy # @param arr int整型一维数组 the array # @return int整型 # class Solution: def candy(self , arr: List[int]) -> int: # write code here n = len(arr) if n == 0: return 0 candies = [1] * n # 每个孩子至少1个糖果 # 从左到右遍历,确保比左边高时糖果更多 for i in range(1, n): if arr[i] > arr[i - 1]: candies[i] = candies[i - 1] + 1 # 从右到左遍历,确保比右边高时糖果更多 for i in range(n - 2, -1, -1): if arr[i] > arr[i + 1]: candies[i] = max(candies[i], candies[i + 1] + 1) return sum(candies)
3、复杂度分析
- 初始分配:每个孩子至少1个糖果。
- 从左到右遍历:确保每个孩子比左侧高分时糖果数更多。
- 从右到左遍历:确保每个孩子比右侧高分时糖果数更多,同时不破坏之前的分配。
- 时间复杂度:两次遍历,O(n)。
- 空间复杂度:使用额外数组存储糖果数,O(n)。