算法入门-贪心2

第八部分:贪心

561.数组拆分(简单)

题目:给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1nmin(ai, bi) 总和最大。

返回该 最大总和

示例 1:

输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
所以最大总和为 4

示例 2:

输入:nums = [6,2,6,5,1,2]
输出:9
解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9

第一种思路:

  1. 排序:首先,通过对输入数组 nums 进行排序,使相邻的数能够成对配对,以最大程度保证 sum 的结果。

  2. 初始化变量:定义一个变量 sum 用于存储结果,leftright 用于指向当前配对的元素。

  3. 遍历并配对

    • 采用 while 循环,确保 right 指针在数组范围内。

    • 在每次循环中,通过 Math.min(nums[left], nums[right]) 获取配对中较小的元素,并累加到 sum 中。由于 nums 已经排序,nums[left]nums[right] 就是形成配对的最小值。

    • 更新 leftright 的位置,以移动到下一个待配对的元素。

  4. 返回结果:当所有配对处理完毕后,返回最终的 sum

class Solution {  // 定义数组对和的求和方法  public int arrayPairSum(int[] nums) {  // 先对数组进行排序  Arrays.sort(nums);  int sum = 0; // 初始化和为0  int left = 0; // 左指针,指向当前配对的第一个数  int right = 1; // 右指针,指向当前配对的第二个数  // 当右指针没有超过数组边界时进行循环  while(right < nums.length) {  // 每次配对取最小的数(即左指针的数),并累加到sum中  sum = sum + Math.min(nums[left], nums[right]);  // 移动到下一个配对  left = right + 1; // 左指针移动到下一个配对的第一个数  right = left + 1; // 右指针移动到下一个配对的第二个数  }  // 返回计算得到的和  return sum;  }  
}  

另外补充(如果对这种思路的可行性有疑问):

分析这种思路的可行性时,我们需要理解题意以及排序的效果。题目要求组成一对数,最大化每对的最小值的总和。通过以下几个步骤,我们可以验证这种方法的有效性。

问题理解:

假设我们有一个数组,目标是将其分为 n 对 (ai, bi),然后求出所有对中最小值 (min(ai, bi)) 的总和。为了使这个总和最大,我们的目标是充分利用较大的数。

排序的思路:

  1. 排序的必要性:如果我们将数组进行排序,较小的数必然会靠前,较大的数会放在后面。这样在选取配对时,我们可以保证将较大的数与其紧邻的小数进行配对,从而让每对的最小值尽可能高。

  2. 合理配对:通过上述排序,我们可以采用每两个数一组的方式进行配对。对于已经排序的数组,配对 (nums[0], nums[1]), (nums[2], nums[3]), ... 这样的方式,使得总和能够达到最大。因为:

    • 对于每一对 (nums[i], nums[i+1]),min(nums[i], nums[i+1]) = nums[i],而 nums[i] 是这对中较小的元素。

    • 因为 nums 是排序过的,nums[i] 的值会尽量大,确保较小的元素不会太小。

示例:

考虑一个简单的例子 [1, 4, 3, 2]

  • 排序后为 [1, 2, 3, 4]

  • 配对方式为 (1, 2), (3, 4),最小值分别为 13,因此总和为 1 + 3 = 4

  • 若我们不排序而随意配对,例如配对 (1, 3), (2, 4),最小值为 12,总和为 1 + 2 = 3,反而得不到最大值。

结论:

通过以上分析,我们可以得出以下结论:

  • 排序后按每两个数一组配对的做法,能确保每对的最小值最大化

  • 因此,这种配对方式是可行的,且可以满足题目要求,获得最大总和

最终计算

由于我们通过遍历的方法直接计算每对的最小值并累加,这种方式保证了额外的效率,同时也完整利用了排序后的结构,最大化了总和。因此,返回的最大总和是可靠的。

整体上,排序并根据排序后的顺序组合元素构成的对,是解这个问题高效且合理的方法。

605.种花问题(简单)

题目:假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组 flowerbed 表示花坛,由若干 01 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false

示例 1:

输入:flowerbed = [1,0,0,0,1], n = 1
输出:true

示例 2:

输入:flowerbed = [1,0,0,0,1], n = 2
输出:false

第一种思路:

"判断能否在不打破种植规则的情况下在花坛内种入 n 朵花,从贪心的角度考虑,应该在不打破种植规则的情况下种入尽可能多的花,然后判断可以种入的花的最多数量是否大于或等于 n。"        链接:. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=O83Ahttps://leetcode.cn/problems/can-place-flowers/solutions/542556/chong-hua-wen-ti-by-leetcode-solution-sojr/

  1. 变量初始化:

    • count:用于记录可以种植的花的数量。

    • m:花坛的长度。

    • prev:用于存储上一个花的位置,初始值为 -1 表示尚未找到种花的位置。

  2. 遍历花坛:

    • 使用一个循环遍历 flowerbed 数组。

    • 当遇到种有花的位置(flowerbed[i] == 1)时,进行以下操作:

  3. 计算可以种花的数量:

    • 如果 prev < 0,说明还没有种花,当前的位置是第一个花的位置。可以在从 0 到当前位置的空地中种花。通过 i / 2 计算可种花数。

    • 如果 prev >= 0,说明之前已经种过花。在当前位置与上一个花位置之间的空地上计算可以种植的花的数量,使用 (i - prev - 2) / 2 来获取可以种植的数量(要减去两个位置,因为中间需要有一个空地)。

  4. 提前返回:

    • 每当计算出 count 后,立即判断是否已经大于等于 n,如果满足条件则返回 true

  5. 处理未种花的情况:

    • 循环结束后,检查是否还没有种花(prev < 0),如果是,可以在整个花坛中种花,计算可种花数量为 (m + 1) / 2(床的长度);

    • 如果 prev >= 0,则计算从最后一个花的位置到花坛结束之间可以种花的数量,使用 (m - prev - 1) / 2

  6. 返回结果:

    • 最后返回 count >= n,检查是否能够种下所需数量的花。

对于第五步:处理未种花的情况

在遍历完整个 flowerbed 数组后,我们需要根据是否种过花(有 1 的位置)来计算在剩余空地上可种植的花的数量。

  1. 如果 prev < 0

    • 这表明整个 flowerbed 数组中都没有种花(即所有元素都是 0)。

    • 在这种情况下,从花坛的开头到结尾都是可种植的空地。计算可种植的数量使用(m + 1) / 2

      。这个数学公式的含义是:

      • 例如,如果花坛长度为 5(即 m = 5),则有 6 个空地位置(例如 0, 0, 0, 0, 0, 0),可以在位置 0, 2, 4 种花。

      • 具体的逻辑如下:

        • 从第一个位置开始,每隔一个位置种一朵花,可以种下 (5 + 1) / 2 = 3 朵花。

  2. 如果 prev >= 0

    • 这表示花坛中至少种过一朵花(存在 1 的位置)。

    • 需要计算从prev(最后一个种花的位置) 到花坛结束的位置之间的空地可以种植的花的数量:

      • 为了保证新种花与现有花之间有空地,根据当前prev位置的计算,空地可以用(m - prev - 1) / 2计算。这是因为:

        • m - prev - 1 是最后一个花和花坛结束之间的空地数量。

        • 为了在这些空地上种花,每种一个花后,下一个种的花又需要隔开一个空地,所以实际上可种下的花数量为 (空地数量) / 2

示例

  • 假设 flowerbed[0, 0, 0, 0, 0],即 m = 5

    • 此时 prev < 0,可以种下 (5 + 1) / 2 = 3 朵花。

  • 假设 flowerbed[1, 0, 0, 0, 1],此时 prev 最后指向的为 4:

    • 计算 m - prev - 15 - 4 - 1 = 0,可以种花的数量为 0 / 2 = 0,因此在最后的位置后没有空地可以种花。

class Solution {  public boolean canPlaceFlowers(int[] flowerbed, int n) {  int count = 0; // 记录可以种植的花朵数量  int m = flowerbed.length; // 获取花坛的长度  int prev = -1; // 用于记录最后一朵花的索引,初始为 -1 表示不存在  // 遍历花坛  for (int i = 0; i < m; i++) {  // 当遇到已经种有花的位置  if (flowerbed[i] == 1) {  // 如果之前没有花(prev < 0),可以在头部空地种花  if (prev < 0) {  count += i / 2; // 从开头到当前位置,可以种的花的数量  } else {  // 计算在 prev 到当前花之间的空地中可以种植的花  count += (i - prev - 2) / 2; // 要减去 2,因为需要一个空地隔开  }  // 如果可种花数量已经大于等于 n,返回 true  if (count >= n) {  return true;  }  // 更新 prev 为当前花的位置  prev = i;  }  }  // 处理没有种过花的情况  if (prev < 0) {  // 如果整个花坛都是空地,可以在所有空地中种花  count += (m + 1) / 2; // 总空地数量的一半  } else {  // 从最后一个花到花坛结束之间的空地  count += (m - prev - 1) / 2; // 计算可以种植的数量  }  // 最终判断是否能够种下 n 朵花  return count >= n;  }  
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Three.js 3D人物漫游项目(下)

本文目录 前言最终效果1、效果回顾2、编写人物模型动画执行类并调用2.1 代码2.2 代码解读2.3 实例化动画类并调用2.4 效果2.4.1 休息动画2.4.2 跑步动画2.4.3 走路动画2.4.4 舞蹈1动画2.4.5 舞蹈2动画3、键盘控制动画3.1 站立休息、走、跑、舞蹈1、舞蹈2代码3.1.1 效果3.2 跳跃…

基于丹摩智算平台-手把手拿下经典目标检测模型 Faster-Rcnn

文章目录 1. 前言1. 1 丹摩智算平台1.2 经典目标检测模型 Faster-Rcnn 2. 前置准备2.1 WindTerm&#xff08;远程连接服务器&#xff09;2.2 项目源码 3. 服务器平台配置3.1 创建实例3.2 远程链接 4. Faster-rcnn 的环境配置4.1 上传文件&#xff0c;解压4.2 安装所需环境 5. 数…

华为HarmonyOS地图服务 1 -- 如何实现地图呈现?

如何使用地图组件MapComponent和MapComponentController呈现地图&#xff0c;效果如下图所示。 MapComponent是地图组件&#xff0c;用于在您的页面中放置地图。MapComponentController是地图组件的主要功能入口类&#xff0c;用来操作地图&#xff0c;与地图有关的所有方法从此…

基于PaddlePaddle复现的PeleeNet

转自AI Studio&#xff0c;原文链接&#xff1a;基于PaddlePaddle复现的PeleeNet - 飞桨AI Studio PeleeNet: An efficient DenseNet architecture for mobile devices 1. 简介 这是一个PaddlePaddle实现的PeleeNet。 PeleeNet是一个高效的卷积神经网络&#xff08;CNN&…

数通。。。

通信&#xff1a;需要介质才能通信电话离信号塔&#xff08;基站&#xff09;越远&#xff0c;信号越弱。信号在基站之间传递。你离路由器越远&#xff0c;信号越差。一个意思 比如想传一张图片&#xff0c;这张图片就是数据载荷 网关&#xff0c;分割两个网络。路由器可以是网…

【贪心算法】贪心算法二

贪心算法二 1.最长递增子序列2.递增的三元子序列3.最长连续递增序列 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.最长递增子序列 题目链…

AI免费UI页面生成

https://v0.dev/chat v0 - UI设计 cursor - 编写代码 参考&#xff1a;https://www.youtube.com/watch?vIyIVvAu1KZ4 界面和claude类似&#xff0c;右侧展示效果和代码 https://pagen.so/

用uniapp 及socket.io做一个简单聊天 升级 9

比这之前优化了以下功能 上线通知 群聊里适时显示在线人数 约请好友 通过好友通过socket 相应端自动变化 PC端可以拉取摄象头拍照 PC端可以录音发送 拉起摄象头发送录象 <template><view class""><scroll-view scroll-y"true" class&…

【Linux篇】常用命令及操作技巧(基础篇)

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明帮助命令常见的七个linux操作终端实用的技巧跟文件目录…

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级,手写实现一个微服务熔断限流器

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级&#xff0c;手写实现一个微服务熔断限流器 服务雪崩熔断、限流、降级熔断降级限流 手写实现一个微服务熔断限流器架构设计代码实现整体逻辑ProtectorAspect#aroundMethod(ProceedingJoinPoint)具体实现1、获取接口对…

智慧农业——InsectMamba利用状态空间模型对害虫进行分类

介绍 论文地址&#xff1a;https://arxiv.org/abs/2404.03611 害虫分类是农业中的一个重要问题。准确识别有害害虫可减少对作物的损害&#xff0c;确保粮食安全和环境的可持续发展。然而&#xff0c;害虫及其自然环境的高度拟态性和物种多样性使得视觉特征的提取极具挑战性。…

Centos7.9 使用 Kubeadm 自动化部署 K8S 集群(一个脚本)

文章目录 一、环境准备1、硬件准备&#xff08;虚拟主机&#xff09;2、操作系统版本3、硬件配置4、网络 二、注意点1、主机命名格式2、网络插件 flannel 镜像拉取2.1、主机生成公私钥2.2、为啥有 Github 还用 Gitee2.3、将主机公钥添加到 Gitee2.3.1、复制主机上的公钥2.3.2、…

< 微积分Calculus >

微积分 微分是把整体分拆为小部分来求它怎样改变 积分是把小部分连接在一起来求整体有多大&#xff0c;可以用来求面积、体积、中点和很多其他有用的东西。 lim极限 函数f(x) -> Q(x) y&#xff1a;x变量&#xff0c;f函数&#xff0c;Q(x)函数体&#xff08;多项式&am…

【Paper Reading】结合 NanoFlow 研究,优化大语言模型服务效率的探索

作者 王伟 PAI引擎团队 近年来&#xff0c;人工智能领域的快速发展推动了大型语言模型的广泛应用&#xff0c;随之而来的是对其服务效率的迫切需求。论文《NanoFlow&#xff1a;Towards Optimal Large Language Model Serving Throughput》提出了一种突破性的新型服务框架&…

CTF 技能树 LOG -GIT泄露 笔记

log 使用虚拟机kali操作 python2 安装 apt-get install python2 进入root用户&#xff0c;下载克隆git hack库 git clone https://github.com/BugScanTeam/GitHack sudo passwd root 修改root 命名密码为root 切换登录 su root 终端进入home/kali/GitHack/ python GitH…

2024年 AI大模型我该买一张什么卡?

有钱啥也不用说&#xff0c;买张最贵的就是了。对囊中羞涩的我还说&#xff0c;我该买张什么样的显卡呢&#xff1f; 我的旧显卡RTX1060 6G&#xff0c;满负荷消耗功率110多瓦&#xff0c;几乎达到设计最大TDP&#xff0c;周日时拿了朋友的RTX3060Ti 8G&#xff0c;发现是锁算…

【中国留学网-注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

手机在网状态查询接口如何用C#进行调用?

一、什么是手机在网状态查询接口&#xff1f; 手机在网状态查询接口是利用实时数据来对手机号码在运营商网络中的状态进行查询的工具&#xff0c;包括正常使用状态、停机状态、不在网状态、预销户状态等。 二、手机在网状态查询适用哪些场景&#xff1f; 例如&#xff1a;商…

Android RecyclerView 实现 GridView ,并实现点击效果及方向位置的显示

效果图 一、引入 implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30 二、使用步骤 1.Adapter public class UnAdapter extends BaseQuickAdapter<UnBean.ResultBean, BaseViewHolder> {private int selectedPosition RecyclerView.NO_POSITIO…

51单片机——LED灯篇

一、LED与单片机P2管脚相连 二、点亮一个LED灯 #include <STC89C5xRC.H> void main() { P2 0xFE; //1111 1110 } P2有8个管脚&#xff0c;对应8个二进制位。 LED灯右侧接电源是正极&#xff08;1&#xff09;&#xff0c;左侧给负极&#xff08;0&#xff09;即可…