当前位置: 首页 > news >正文

力扣每日一题——分发糖果

目录

题目链接:135. 分发糖果 - 力扣(LeetCode)

题目描述

解法一:两次遍历贪心法

Java写法:

C++写法:

运行时间

时间复杂度和空间复杂度

时间复杂度:O(n)

空间复杂度:O(n)

总结


题目链接:135. 分发糖果 - 力扣(LeetCode)

注:下述题目描述和示例均来自力扣

题目描述

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

提示:

  • n == ratings.length
  • 1 <= n <= 2 * 10^4
  • 0 <= ratings[i] <= 2 * 10^4

解法一:两次遍历贪心法

        这道题目的核心就是给一排孩子分糖果,要求每个孩子至少一颗,而且相邻的两个孩子里,评分更高的那个必须拿到更多糖果。咱们的目标是用最少的糖果数满足这些条件。解题思路其实挺直观的,就是用两次遍历来调整糖果分配,下面我分段讲讲具体怎么操作。

        首先,先给每个孩子都发一颗糖,这是最基本的,因为题目要求每人至少一个。这样初始化后,咱们就有了一个起点,后面再根据评分高低来额外加糖。这一步很简单,但很重要,它确保了最低要求被满足,后续调整都在这个基础上进行。

        接着,从左往右遍历一遍孩子。这次只看每个孩子和他左边邻居的关系:如果当前孩子的评分比左边的高,那他的糖果就得比左边的多一颗。比如左边孩子有2颗糖,他就得拿3颗。这样遍历完,就能保证所有“右边比左边评分高”的情况都满足了,但这时候“左边比右边评分高”的情况可能还没处理好,因为这次遍历只考虑了左邻居。

        然后,从右往左再遍历一遍。这次只看每个孩子和他右边邻居的关系:如果当前孩子评分比右边的高,那他的糖果应该比右边的多。但这里有个关键点——不能直接设成“右边糖果数+1”,因为可能从左往右遍历时已经给他分配了更多糖(比如因为左边邻居的关系)。所以要用max函数,比较当前已有的糖果数和“右边糖果数+1”,取更大的那个。这样既不会破坏第一次遍历的结果,又能确保右边条件也满足。

        最后,把每个孩子手里的糖果数加起来,就是最少需要的总数了。这个方法之所以高效,是因为它分两次处理了相邻关系,每次只专注一侧(先左后右),通过max操作协调冲突,避免重复发糖或者遗漏条件。整体上,时间复杂度是O(n),空间上用了额外数组,但很实用。


Java写法:

public class Solution {public int candy(int[] ratings) {if (ratings == null || ratings.length == 0) return 0;int n = ratings.length;int[] candies = new int[n];Arrays.fill(candies, 1); // 初始化每人至少1颗糖果// 从左到右遍历:确保右侧高分孩子糖果 > 左侧for (int i = 1; i < n; i++) {if (ratings[i] > ratings[i - 1]) {candies[i] = candies[i - 1] + 1;}}// 从右到左遍历:确保左侧高分孩子糖果 > 右侧,并取max保证两边条件for (int i = n - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) {candies[i] = Math.max(candies[i], candies[i + 1] + 1);}}// 计算总糖果数int total = 0;for (int num : candies) {total += num;}return total;}
}

C++写法:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int candy(vector<int>& ratings) {int n = ratings.size();if (n == 0) return 0;vector<int> candies(n, 1); // 初始化每人至少1颗糖果// 从左到右遍历:确保右侧高分孩子糖果 > 左侧for (int i = 1; i < n; i++) {if (ratings[i] > ratings[i - 1]) {candies[i] = candies[i - 1] + 1;}}// 从右到左遍历:确保左侧高分孩子糖果 > 右侧,并取maxfor (int i = n - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) {candies[i] = max(candies[i], candies[i + 1] + 1);}}// 计算总糖果数int total = 0;for (int num : candies) {total += num;}return total;
}int main() {vector<int> ratings = {1, 2, 2}; // 示例输入cout << "最少糖果数: " << candy(ratings) << endl; // 输出 4return 0;
}

运行时间

时间复杂度和空间复杂度

时间复杂度:O(n)

  • ​原因​​:算法仅需两次独立遍历数组:
    1. ​从左到右遍历​​:检查每个孩子与左邻居的评分关系,若评分更高则糖果数+1。
    2. ​从右到左遍历​​:检查每个孩子与右邻居的评分关系,若评分更高则更新糖果数为 max(当前值, 右邻居糖果数+1)
  • 每次遍历耗时 O(n),总时间复杂度为 O(n)。

空间复杂度:O(n)

  • ​原因​​:需要额外长度为 n 的数组 candies 存储每个孩子的糖果数。



总结

        本文介绍了LeetCode题目"分发糖果"的贪心解法。题目要求给一排孩子分糖果,满足每个孩子至少1颗且相邻孩子中评分高的糖果更多。解法采用两次遍历:第一次从左到右确保右高分孩子糖果更多,第二次从右到左处理左高分情况并用max函数维持条件。Java和C++实现均使用O(n)时间和空间复杂度,其中空间开销用于存储糖果分配数组。该方法高效协调了相邻关系,确保最少糖果数的同时满足题目所有条件。

http://www.xdnf.cn/news/779743.html

相关文章:

  • React Native图片预加载:让你的应用图片预览像德芙一样丝滑
  • 实验设计与分析(第6版,Montgomery著,傅珏生译) 第10章拟合回归模型10.9节思考题10.1 R语言解题
  • Python趣学篇:从零打造智能AI井字棋游戏(Python + Tkinter + Minimax算法)
  • 编译 Linux openssl
  • 黑客利用GitHub现成工具通过DevOps API发起加密货币挖矿攻击
  • C++语法系列之类型转换
  • Catboost算法原理及应用场景
  • 生成对抗网络(GAN)基础原理深度解析:从直观理解到形式化表达
  • C语言学习—数据类型20250603
  • NLP学习路线图(二十):FastText
  • K8S上使用helm部署 Prometheus + Grafana
  • Grafana-State timeline状态时间线
  • 乐播视频v4.0.0纯净版体验:高清流畅的视听盛宴
  • Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(六):图片上传功能
  • Linux(线程概念)
  • 《深入解析SPI协议及其FPGA高效实现》-- 第三篇:FPGA实现关键技术与优化
  • Docker 安装 Centos
  • Python与数据分析期末复习笔记
  • Web3如何重塑数据隐私的未来
  • LeetCode 139. 单词拆分(Word Break) - 动态规划深度解析
  • SVM详解
  • GROM快速上手
  • Java线程状态及其流转
  • 互联网大厂智能体平台体验笔记字节扣子罗盘、阿里云百炼、百度千帆 、腾讯元器、TI-ONE平台、云智能体开发平台
  • C++仿RabbitMQ实现消息队列
  • jwt token验证
  • 【Linux】线程互斥
  • Apache Druid
  • 安全-JAVA开发-第一天
  • AbMole| 3-Methyladenine (3-MA) (M2296;3-甲基腺嘌呤)