leetcode 135. Candy 三种解法

it2026-02-12  7

题意

给每个孩子分糖果,如果这个孩子的rating比相邻的孩子高,那么他分到的糖果就要比他多,求最少需要多少糖果。

There are N children standing in a line. Each child is assigned a rating value.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.Children with a higher rating get more candies than their neighbors.

What is the minimum candies you must give?

Example 1:

Input: [1,0,2] Output: 5 Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:

Input: [1,2,2] Output: 4 Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively. The third child gets 1 candy because it satisfies the above two conditions.

test cases

[3,2,1,1,2,4,3,2,1,0,0] [1,0,2] [1,0,2,2,3,4,5,6,7,7,8,9,0,1,2,3,2,1,1,2,1,0] [3,2,1,1,2,3,2,2,3,4,2,2,1] [] [1,2,2,2,1,1,3,1,2,10,20,19,18,17,16,15,4,3,2,1,2,2,1,1,0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0,10] [1] [0]

解1 只遍历一遍即得出结果

时间复杂度O(N)

[3,2,1,1,2,4,3,2,1,0,0]对这个用例,分法应该为:

[3,2,1,1,2,5,4,3,2,1,1]

过程为:

[1]

[2,1]

[3,2,1]

[3,2,1,1]

[3,2,1,1,2]

[3,2,1,1,2,3]

[3,2,1,1,2,3,1]

[3,2,1,1,2,3,2,1]

[3,2,1,1,2,4,3,2,1]

[3,2,1,1,2,5,4,3,2,1]

[3,2,1,1,2,5,4,3,2,1,1]

思路:维护3个变量:当前高度、前最大高度、当前台阶高度。

如果比前一个孩子分高,

​ 如果是第一次上升,那么当前台阶高度=2,

​ 如果不是第一次上升,那么当前台阶高度++;

​ 结果加上当前台阶高度。

如果比前一个孩子分低,

​ 如果不是第一次下降,那么台阶高度++;

​ 如果是第一次下降,那么台阶高度=1;

​ 结果加上 high < maxHigh ? high : maxHigh + 1;

如果相等,

​ 与前面隔断。

讲不清楚,也很复杂,直接上代码

// Runtime: 2 ms, faster than 95.29% of Java online submissions for Candy. //Memory Usage: 39.7 MB, less than 16.42% of Java online submissions for Candy. public int candy(int[] ratings) { if (ratings == null || ratings.length == 0) return 0; int prev = ratings[0]; int sum = 1; int level = 1; int high = 1; int maxHigh = 1; for (int i = 1; i < ratings.length; i++) { if (ratings[i] > prev) { if (level++ == 1) high = 2; else high++; maxHigh = high; sum += level; } else if (ratings[i] < prev) { if (level == 1) { high++; } else { level = 1; high = 1; } sum += high < maxHigh ? high : maxHigh + 1; if (high == maxHigh) high++; maxHigh = Math.max(high, maxHigh); } else { level = 1; high = 1; maxHigh = 1; sum += 1; } prev = ratings[i]; } return sum; }

解2

因为有排序,时间复杂度O(NlogN(N))

贪心,思路就比较简单了,实现也简单,只是效率低一些。

永远找出分数最小的一个,如果比邻居高,那么糖果就要比高的邻居还要高,并且取最大值,分配。

根据这个思路,我很快就实现了,结果花费了20ms,花费了解1十倍的时间。

// 贪心 // Runtime: 20 ms, faster than 11.77% of Java online submissions for Candy. //Memory Usage: 45.7 MB, less than 16.42% of Java online submissions for Candy. public int candy(int[] ratings) { if (ratings == null || ratings.length == 0) return 0; Map<Integer, List<Integer>> indexes = new HashMap<>(); int[] candies = new int[ratings.length]; for (int i = 0; i < ratings.length; i++) { indexes.putIfAbsent(ratings[i], new ArrayList<>()); indexes.get(ratings[i]).add(i); } int[] sorted = Arrays.copyOf(ratings, ratings.length); Arrays.sort(sorted); int sum = 0; for (int i = 0; i < sorted.length; i++) { if (i > 0 && sorted[i] == sorted[i - 1]) continue; for (Integer j : indexes.get(sorted[i])) { if (j > 0 && ratings[j] > ratings[j - 1]) candies[j] = candies[j - 1] + 1; if (j < ratings.length - 1 && ratings[j] > ratings[j + 1]) candies[j] = Math.max(candies[j], candies[j + 1] + 1); if (candies[j] == 0) candies[j] = 1; sum += candies[j]; } } return sum; }

解3 遍历两次,从左往右一次,从右往左依一次

时间复杂度O(N)

用两种方法做了之后网上看了别人的解法,发现了这种思路简单,容易实现,而且效率也高的做法。

非常赞,其实刚看到这道题的时候就想到了,但是当时就想着只遍历一次,然后在解1的路上越走越远,好在还是做出来了,但是不如解3的方法。

// Runtime: 1 ms, faster than 100.00% of Java online submissions for Candy. //Memory Usage: 39.7 MB, less than 16.42% of Java online submissions for Candy. public int candy3(int[] ratings) { int[] extraCandies = new int[ratings.length]; for (int i = 1; i < ratings.length; i++) { if (ratings[i] > ratings[i - 1]) { extraCandies[i] = extraCandies[i - 1] + 1; } } for (int i = ratings.length - 2; i >= 0; i--) { if (ratings[i + 1] < ratings[i]) extraCandies[i] = Math.max(extraCandies[i], extraCandies[i + 1] + 1); } int sum = 0; for (int extraCandy : extraCandies) { sum += extraCandy; } return sum + ratings.length; }
最新回复(0)