代码随想录刷题笔记 DAY 32 | K 次取反后最大化的数组和 No.1005 | 加油站 No.134 | 分发糖果 No.135

文章目录

    • Day 32
      • 01. K 次取反后最大化的数组和(No. 1005)
        • 1.1 题目
        • 1.2 笔记
        • 1.3 代码
      • 02. 加油站(No. 134)
        • 2.1 题目
        • 2.2 笔记
        • 2.3 代码
      • 03. 分发糖果(No. 135)
        • 3.1 题目
        • 3.2 笔记
        • 3.3 代码

Day 32

01. K 次取反后最大化的数组和(No. 1005)

题目链接

代码随想录题解

1.1 题目

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

  • 选择某个下标 i 并将 nums[i] 替换为 -nums[i]

重复这个过程恰好 k 次。可以多次选择同一个下标 i

以这种方式修改数组后,返回数组 可能的最大和

示例 1:

输入:nums = [4,2,3], k = 1
输出:5
解释:选择下标 1 ,nums 变为 [4,-2,3] 。

示例 2:

输入:nums = [3,-1,0,2], k = 3
输出:6
解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] 。

示例 3:

输入:nums = [2,-3,-1,5,-4], k = 2
输出:13
解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4] 。

提示:

  • 1 <= nums.length <= 104
  • -100 <= nums[i] <= 100
  • 1 <= k <= 104
1.2 笔记

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本题中的数组会有三种构成方式:

  • 全是正数
  • 全是负数
  • 正数和负数混合型的数组
  1. 而对于全是正数的数组如果又 k 次取反机会的话,最好的情况肯定是 k 是一个偶数,取偶数次反的最大和就是原数组的和,但如果是奇数的话,就需要将数组进行排序来找到最小的那个数字,整个数组减去最小的那个数就是最大和。
  2. 如果数组全是负数的话,最好的情况肯定是尽可能利用这 k 次取反 尽可能 将所有的负数变成正数
    • 如果完全变成正数数组但是 k 还是没有消耗完,再次返回全是正数的情况
  3. 如果数组是正数和负数混合的情况那和全是负数是相同的处理方式,尽可能多的将负数变为正数

这样就构成了本题的贪心策略,仔细想想没有反例。

为了确定正数和负数的界限以及最小的正数在哪里,要将数组进行排序,但是注意,如果将所有的负数都遍历完后 k 还有剩余就需要 再次排序 来获取最小的正数。

先尽可能多的将负数变为正数:

		Arrays.sort(nums);
// 先尽可能将所有的负数都去除掉
        for (int i = 0; i < nums.length && nums[i] < 0; i++) {
            if (k == 0 || i > nums.length - 1) {
                // 说明使用 k 次取反没有将所有的负数取完
                return getSum(nums);
            }
            nums[i] = 0 - nums[i];
            k--;
        }

如果在这个途中使得 k 变为了负数,那此时的结果就是最大的。

遍历结束后说明是此时数组全部变为正数

    if (k % 2 == 0) {
   	 return getSum(nums);
    } else {
    	Arrays.sort(nums);
    	return getSum(nums) - nums[0] - nums[0];
    }

此时再去判断 k 是奇数还是偶数来进行处理。

1.3 代码
class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int res = 0;
        Arrays.sort(nums);
        // 先尽可能将所有的负数都去除掉
        for (int i = 0; i < nums.length && nums[i] < 0; i++) {
            if (k == 0 || i > nums.length - 1) {
                // 说明使用 k 次取反没有将所有的负数取完
                return getSum(nums);
            }
            nums[i] = 0 - nums[i];
            k--;
        }
        if (k % 2 == 0) {
            return getSum(nums);
        } else {
            Arrays.sort(nums);
            return getSum(nums) - nums[0] - nums[0];
        }
        
    }
    public int getSum(int[] nums) {
        int res = 0;
        for (int i : nums) {
            res += i;
        }
        return res;
    }
}

02. 加油站(No. 134)

2.1 题目

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gascost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

示例 1:

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

示例 2:

输入: gas = [2,3,4], cost = [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

提示:

  • gas.length == n
  • cost.length == n
  • 1 <= n <= 105
  • 0 <= gas[i], cost[i] <= 104
2.2 笔记

本题的解法可以说是非常的巧妙。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由题目中给出的两个数组可以推出一个新的数组 rest[gas.length] 这个数组表示从这个加油站 到达下一个加油站 剩余的油量。

如果这个数组求和得到的结果小于零,那么肯定无法环绕。

但如果这个数组求和大于等于零的话,那就一定能环绕一圈吗?

答案是一定可以,搞清楚这个就是解题的关键了。

肯定可以将整段路程(rest 数组)分为两个阶段:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先来确定这两个阶段的的和,答案肯定是正数或者零,那假如题目中给的恰好是 0,那第一段的和就恰好是第二段的 相反数,也就是如果 通过第二段 到达终点,此时的油量恰好能支持他走回来。

也就是说此时的题目就变成了寻找从哪个节点开始 走到终点 油量为正数

首先构建出 rest 数组

    int[] rest = new int[gas.length];
    int sum = 0;
    for(int i = 0; i < gas.length; i++) {
        sum += gas[i] - cost[i];
        rest[i] = gas[i] - cost[i];
    }

然后来判断这个数组的总和是否大于等于 0

		 if (sum < 0) {
            return -1;
        }

然后去寻找这个节点,从节点 0 开始寻找,如果途中发现 sum 变为负数就从 i + 1 继续寻找,直到遍历完成一定能找到一个节点。

		for (int i = 0; i < rest.length; i++) {
            currentSum += rest[i];
            if (currentSum < 0) {
                currentSum = 0;
                startIndex = i + 1;
            }
        }

此时的节点就是结果。

简化一下,写出代码。

2.3 代码
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int sum = 0; // rest 数组的总数
        int currentSum = 0;
        int startIndex = 0;
        for(int i = 0; i < gas.length; i++) {
            currentSum += gas[i] - cost[i];
            if (currentSum < 0) {
                currentSum = 0;
                startIndex = i + 1;
            }
        }
        if (sum < 0) {
            return -1;
        }
        return startIndex;
    }
}

03. 分发糖果(No. 135)

题目链接

代码随想录题解

3.1 题目

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 * 104
  • 0 <= ratings[i] <= 2 * 104
3.2 笔记

本题难的地方就在于一个节点的变化可能会导致整个分发情况的变化。

所以本题一定要 整体 来求解,即一次只考虑一种情况:左边大于右边或者右边大于左边

这样遍历一个整体就能保证最后的结果满足其中的一个,通过两次对整体的修改就能得到最终的结果。

先从头开始遍历处理,这里必须要注意遍历顺序的有效性,因为后面是要 在前面的基础上 去做一个自增操作,所以从前往后遍历只能是解决 右边比左边大 的情况,这样才能保证操作是准确的。

从前向后遍历不断更新,可以得到如下的数组

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

		// 先从前向后去遍历,右边比左边大的情况
        for (int i = 1; i < ratings.length; i++) {
            nums[i] = 1;
            if (ratings[i] > ratings[i - 1]) {
                nums[i] = nums[i - 1] + 1;
            }
        }

这就保证右边比左边大的情况全部处理了,现在还需要处理左边比右边大的情况,此时为了结果的有效就需要从后往前去遍历了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意上图中的 2 + 1 中的 2 是后一个节点的 2 而不是第一次遍历得到的 2

// 再从后往前去遍历,左边比右边大的情况
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                nums[i] = Math.max(nums[i], nums[i + 1] + 1);
            }
        }

第二次遍历就会出现某个节点的糖果数量的改变,一旦改变就说明这个节点 大于左边的节点,同时大于右边的节点,那此时这个节点的值就应该是其中的最大值

nums[i] = Math.max(nums[i], nums[i + 1] + 1);

通过这种前后遍历来分别处理 改变一个节点的数值造成的影响 就能保证不会出现纰漏

3.3 代码
class Solution {
    public int candy(int[] ratings) {
        int[] nums = new int[ratings.length];
        Arrays.fill(nums, 1);
        // 先从前向后去遍历,右边比左边大的情况
        for (int i = 1; i < ratings.length; i++) {
            nums[i] = 1;
            if (ratings[i] > ratings[i - 1]) {
                nums[i] = nums[i - 1] + 1;
            }
        }
        // 再从后往前去遍历,左边比右边大的情况
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                nums[i] = Math.max(nums[i], nums[i + 1] + 1);
            }
        }
        return Arrays.stream(nums).sum();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/409287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

测试C#使用PuppeteerSharp将网页生成PDF文件

微信公众号“DotNet开发跳槽”、“dotNET跨平台”、“DotNet”发布了几篇将网页生成图片或pdf文件的文章&#xff08;参考文献2-5&#xff09;&#xff0c;其中介绍了使用puppeteer-sharp、Select.HtmlToPdf、iTextSharp等多种方式实现html转图片或pdf&#xff0c;正好最近有类…

探秘SuperCLUE-Safety:为中文大模型打造的多轮对抗安全新框架

探秘SuperCLUE-Safety&#xff1a;为中文大模型打造的多轮对抗安全新框架 进入2023年以来&#xff0c;ChatGPT的成功带动了国内大模型的快速发展&#xff0c;从通用大模型、垂直领域大模型到Agent智能体等多领域的发展。但是生成式大模型生成内容具有一定的不可控性&#xff0…

本地部署ChatGPT

发布一下我之前做的一个本地大模型部署,不需要API key,但要有自己的账号 利用Docker 的Pandora做本地ChatGPT模型部署 先下载安装Docker,设置好运行如下 会要求升级核心,cmd运行如下命令就OK 安装Pandora 再管理员cmd中输入如下命令拉取Pandora镜像 docker pull pengzhi…

SpringBoot -【BeanFactory】基础使用及应用场景

1.介绍 在 Spring 框架中&#xff0c;BeanFactory 是 Spring IoC 容器的核心接口&#xff0c;负责管理 bean 的创建、配置和装配。它是 Spring IoC 容器的基础。BeanFactory 接口定义了一系列方法&#xff0c;用于管理和访问容器中的 bean 对象。 BeanFactoryAware 用于在 Sp…

AD24-Gerber生产文件输出及整理

一、Gerber生产文件输出 1、先进行规则检查 2、Gerber Files输出 3、钻孔文件 4、IPC网表 5、坐标文件 二、Gerber Flies文件整理 1、CAM 2、SMT 3、ASM 4、PRJ 5、DXF

Django定时任务之django_apscheduler使用

Django定时任务之django_apscheduler使用 今天在写一个任务需求时需要用到定时任务来做一部分数据处理与优化&#xff0c;于是在了解完现有方法&#xff0c;结合自己需求决定使用django_apscheduler&#xff0c;记录一下过程&#xff0c;有几篇值得参考的文章放在结尾&#xf…

8.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-游戏底层功能对接类GameProc的实现

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;通过逆向分析确定游戏明文接收数据过程 码云地址&#xff08;master 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/titan 码云版本号&#xff1a;bcf7559184863febdcad819e48aaa…

应用配置管理

一、Pod 配置管理 可变配置用 ConfigMap&#xff1b; 敏感信息用 Secret&#xff1b; 身份认证用 ServiceAccount 这几个独立的资源来实现的&#xff1b; 资源配置用 Resources&#xff1b; 安全管控用 SecurityContext&#xff1b; 前置校验用 InitContainers 这几个在 …

在VSCode中新配置一个ros项目

如何从零开始配置一个ros项目 预先准备初始化ros工程运行hello_ros进行第一个示例进行编译测试 预先准备 首先要在vscode中安装&#xff08;必须安装的&#xff09;&#xff1a;ros&#xff0c;c&#xff0c;cmake&#xff0c;cmake tools&#xff08;补全camkelist文件&#…

Mcal篇 配置Dio模块输出

1、打开EB&#xff0c;新建工程 AUTOSAR version 4.0.3 2、导入Mcu 、Dio、Port三个模块 发现 verify 选项是灰色&#xff0c;重启EB verify&#xff0c;0 Errors 0 Warnings 验证OK 3、配置 clock 时钟 4、配置Dio 目标是 配置15.0~15.3 四个引脚 输出 改为DioPort_…

第2.5章 StarRocks表设计——行列混存表

注&#xff1a;本篇文章阐述的是StarRocks- 3.2.3版本的行列混存表 一、概述 1.1 背景 StarRocks 基于列存格式引擎构建&#xff0c;在高并发场景&#xff0c;用户希望从系统中获取整行数据。当表宽时&#xff0c;列存格式将放大随机IO和读写。自3.2.3开始&#xff0c;StarRo…

DDS通信协议

DDS&#xff08;Data Distribution Service&#xff09;是一套通信协议和 API 标准&#xff1b;它提供了以数据为中心的连接服务&#xff0c;基于发布者-订阅者模型。这是一套中间件&#xff0c;它提供介于操作系统和应用程序之间的功能&#xff0c;使得组件之间可以互相通信。…

Qt Creator如何快速添加函数说明

/***************************************************************** *函数名称&#xff1a;Name *功能描述&#xff1a;详细描述 *参数说明&#xff1a;参数说明 *返回值&#xff1a; 返回值说明 ******************************************************************/

图像生成评价指标:Inception Score和 FID 的定义,区别,联系。

IS&#xff08;Inception Score&#xff09;和FID&#xff08;Frechet Inception Distance score&#xff09;的定义&#xff0c;区别&#xff0c;联系&#xff1a; IS&#xff08;Inception Score&#xff09; 定义&#xff1a; IS基于Google的预训练网络Inception Net-V3。…

【服务发现--ingress】

1、ingress介绍 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 是对集群中服务的外部访问进行管理的 API 对象&#xff0c;典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟…

贪心算法---前端问题

1、贪心算法—只关注于当前阶段的局部最优解,希望通过一系列的局部最优解来推出全局最优----但是有的时候每个阶段的局部最优之和并不是全局最优 例如假设你需要找给客户 n 元钱的零钱&#xff0c;而你手上只有若干种面额的硬币&#xff0c;如 1 元、5 元、10 元、50 元和 100…

【变压器故障诊断分类及预测】基于GRNN神经网络

课题名称&#xff1a;基于GRNN神经网络的变压器故障诊断分类及预测 版本日期&#xff1a;2024-02-10 运行方式&#xff1a;直接运行GRNN0507.m文件 代码获取方式&#xff1a;私信博主或QQ&#xff1a;491052175 模型描述&#xff1a; 对变压器油中溶解气体进行分析是变压器…

JavaAPI常用类01

目录 概述 Object类 Object类_toString() 代码展示 重写toString()方法前后输出 Object类_equals() 代码展示 重写equals()方法前后输出对比 Arrays类 equals()方法 Binary Search&#xff08;二分查找&#xff09; copyOf()方法 sort()方法 了解sort()方法 进阶…

在使用nginx的时候快速测试配置文件,并重新启动

小技巧 Nginx修改配置文件后需要重新启动&#xff0c;常规操作是启动在任务管理器中关闭程序然后再次双击nginx.exe启动&#xff0c;但是使用命令行就可以快速的完成操作。 将cmd路径切换到nginx的安装路径 修改完成配置文件后 使用 nginx -t校验nginx 的配置文件是否出错 …

Python入门必学:reverse()和reversed()的区别

Python入门必学&#xff1a;reverse()和reversed()的区别 &#x1f4c5;2024年02月25日 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程…