数组与贪心算法——605、121、122、561、455、575(5简1中)

news/2024/9/17 9:48:45/ 标签: 贪心算法, 算法

605. 种花问题(简单)

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

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

 解法一、贪心

先种满,数数满了多出来几朵,再讨论n在不在范围内。对边界要求有点高。。

题解里较完美的一个if条件:

 if ((i == 0 || f[i - 1] == 0) && f[i] == 0 && (i == m - 1 || f[i + 1] == 0))

class Solution {public boolean canPlaceFlowers(int[] flowerbed, int n) {int num = flowerbed.length;int res = 0;if(num == 1){return n==0 || flowerbed[0] == 0 && n == 1 ;}else if(num == 2){return n==0 || ((flowerbed[0] == 0 && flowerbed[1] == 0) && n == 1);}for(int i = 0; i < num;i++){if(i == 0 && flowerbed[0] == 0 && flowerbed[1] == 0){flowerbed[0] = 1;res++;}else if(i == num-1 && flowerbed[i-1] == 0 && flowerbed[i] == 0){res++;}else if(i > 0 && i < num - 1 && flowerbed[i] != 1 && flowerbed[i+1] != 1 && flowerbed[i-1] != 1){flowerbed[i] = 1;res++;}}return n <= res;}
}

121. 买卖股票的最佳时机(简单)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。 

解法一、暴力(超时)

一开始确实想不动脑子来着(

public class Solution {public int maxProfit(int[] prices) {int maxprofit = 0;for (int i = 0; i < prices.length - 1; i++) {for (int j = i + 1; j < prices.length; j++) {int profit = prices[j] - prices[i];if (profit > maxprofit) {maxprofit = profit;}}}return maxprofit;}
}

解法二、类dp

但不需要维护一个dp数组,只需要维护一个从0-k(0<=k<n)的最小买入值就好

class Solution {public int maxProfit(int[] prices) {int min = prices[0];int profit = 0;for(int i = 1;i < prices.length;i++){profit = Math.max(prices[i] - min,profit);min = Math.min(min,prices[i]);}return profit;}
}

122. 买卖股票的最佳时机 II(中等)

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

解法一、贪心

本质思想就是一旦有钱赚马上买入卖出。注意:贪心只能模拟思想过程,不是实际交易过程。如对于[1,3,4],贪心是1买3卖、3买4卖,交易过程是1买4卖。两者利益等价,行为不等价。

本题还有很多其他类型,尤其是dp/递增栈,但果然还是放在dp专题里做比较好吧~这方面就不贪心了!

class Solution {public int maxProfit(int[] prices) {int profit = 0;if(prices.length < 2)return 0;for(int i = 1;i < prices.length;i++){if(prices[i] > prices[i-1])profit += prices[i] - prices[i-1];}return profit;}
}

561. 数组拆分(简单) 

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

返回该 最大总和 。

解法一、排序

要取最大,也就是尽量把小的和小的堆一起,大的和大的堆一起。所以先排序,排序后数组偶数位置的和就是所求。

class Solution {public int arrayPairSum(int[] nums) {Arrays.sort(nums);int n = nums.length,sum = 0;for(int i = 0;i < n;i +=2){sum+=nums[i];}return sum;}
}

解法二、数组排序

从代码示例那边看到的。这个和之前看到的那个取maxSum、minSum然后/2的技法其实有点像,桶排序虽然麻烦但是耗时真的很低。这里直接取gpt的解释吧。

  • index 用来追踪当前已经遍历的数值的累计个数。

  • res 是用于存储最终的结果。

每当 arr[i] > 0,意味着索引 i 对应的数值在 nums 中出现过,代码会根据当前的 index 和 arr[i] 的值来计算部分结果:

  • ((index + 1) % 2 + arr[i]) / 2 这个表达式与确定中位数位置相关,它用于决定是否将该数值纳入 res的计算。

  • (i - 10000) 将索引 i 转换回原来的数值范围(因为我们之前对 nums 的数值进行了偏移处理)。

最后,index = index + arr[i] 用于更新累计的数值个数。

((index + 1) % 2 + arr[i]) / 2 这个表达式的作用是用于控制在遍历过程中,是否选择将当前 i 对应的数值 (即 i - 10000) 贡献给最终的 res 结果。让我们一步一步拆解它的含义:

1. index + 1

index 是用来记录遍历到当前位置之前,总共处理过的元素的个数。index + 1 表示当前的元素是所有已经遍历过的元素中的第几个。

2. % 2

对 index + 1 取模 2 的作用是确定当前这个元素是偶数还是奇数。它会返回两种情况:

  • 当 index + 1 是奇数时,(index + 1) % 2 = 1

  • 当 index + 1 是偶数时,(index + 1) % 2 = 0

这个结果决定了后续表达式的一个偏移调整。

3. arr[i]

arr[i] 表示当前索引 i 对应的数值在 nums 数组中出现的次数。

4. ((index + 1) % 2 + arr[i])

这一步是把 (index + 1) % 2 和 arr[i] 的值加起来:

  • 如果当前是奇数个元素 ((index + 1) % 2 = 1),那么结果就是 1 + arr[i]

  • 如果当前是偶数个元素 ((index + 1) % 2 = 0),那么结果就是 0 + arr[i]

这相当于调整了 arr[i] 的数值,使得某些条件下它多加 1 或不变,这和计算中位数的位置有关系。

5. / 2

这一步是对整个表达式进行除以 2:

  • 如果 arr[i] 是偶数或者 (index + 1) % 2 是 0,那么 (index + 1) % 2 + arr[i] 是偶数,除以 2 后返回一个整数。

  • 如果 arr[i] 是奇数,并且 (index + 1) % 2 = 1,这会使得奇数变为偶数的一半。

总体意义

这个表达式的作用在于,在遍历过程中,根据当前遍历的元素顺序(index)以及该元素的出现次数(arr[i]),判断要不要取一半的数值(除以 2),这样就可以控制贡献给 res 的数值。在处理中位数相关的算法时,这个操作可以帮助判断中位数所在位置以及应取多少值。

举例

假设:

  • arr[i] = 3 表示当前这个数出现了 3 次,

  • index + 1 = 5 表示当前是第 5 个元素,

那么:

  • (index + 1) % 2 = 1,所以 ((index + 1) % 2 + arr[i]) = 1 + 3 = 4

  • / 2 后结果是 2,表示将当前的数值贡献 2 次。

这个操作对中位数或者其他与位置相关的统计操作有帮助。

class Solution {public int arrayPairSum(int[] nums) {if (nums.length <= 1800) {Arrays.sort(nums);int sum = 0;for (int i = 0; i < nums.length; i = i + 2) {sum = sum + nums[i];}return sum;} else {// 在该用数组排序的时候又把这件事忘了个干净int[] arr = new int[20001];for (int i = 0; i < nums.length; i++) {arr[nums[i] + 10000]++;}int index = 0;int res = 0;for (int i = 0; i < arr.length; i++) {if (arr[i] > 0) {res = res + ((index + 1) % 2 + arr[i]) / 2 * (i - 10000);index = index + arr[i];}}return res;}}
}

455. 分发饼干(简单)

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。

解法一、排序+双指针

先排序。如果饼干比当前孩子胃口值小,那么饼干值往后挑。否则,i++,j++,计入结果。

class Solution {public int findContentChildren(int[] g, int[] s) {int i = 0,j = 0,res = 0;Arrays.sort(g);Arrays.sort(s);while(i < g.length && j < s.length){while(i < g.length && j < s.length && s[j] < g[i])j++;if(i < g.length && j < s.length && s[j] >= g[i]){i++;j++;res++;}}return res;}
}

稍微改善一些(2ms)的情况。在这次的循环里,以孩子都吃到为前提条件,如果饼干用完,则结束,减少了反复判断。

 public int findContentChildren0(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int result = 0;int j = 0;for (int i = 0; i < g.length; i++) {while (j < s.length && g[i] > s[j]) {j++;}if (j >= s.length) {break;}j++;result++;}return result;}

575. 分糖果(简单) 

Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。

医生建议 Alice 要少摄入糖分,只吃掉她所有糖的 n / 2 即可(n 是一个偶数)。Alice 非常喜欢这些糖,她想要在遵循医生建议的情况下,尽可能吃到最多不同种类的糖。

给你一个长度为 n 的整数数组 candyType ,返回: Alice 在仅吃掉 n / 2 枚糖的情况下,可以吃到糖的 最多种类数

解法一、枚举

只要品种不同就过,如果达到满值就break 

class Solution {public int distributeCandies(int[] candyType) {int res = 0,n2 = candyType.length;Arrays.sort(candyType);for(int i = 0;i < n2;i++){if(res == n2/2)return n2/2;res++;while(i < n2-1 && candyType[i]==candyType[i+1])i++;}return res;}
}

解法二、数据结构去重

 本质上就是统计种类,然后返回Math.min(n/2,m)的东西,只要能够统计种类,什么方法都可以。

class Solution {public int distributeCandies(int[] candyType) {Set<Integer> set = new HashSet<Integer>();for (int candy : candyType) {set.add(candy);}return Math.min(set.size(), candyType.length / 2);}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/distribute-candies/solutions/1072396/fen-tang-guo-by-leetcode-solution-l4f6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

碎碎念

  • 605需要转换思维,121、122是一个系列,考察dp还蛮有意思的。其中122的贪心做法比其他想法都要简单。感觉贪心里目前用到排序的次数很多

http://www.ppmy.cn/news/1522907.html

相关文章

【2024高教社杯全国大学生数学建模竞赛】B题模型建立求解

目录 1问题重述1.1问题背景1.2研究意义1.3具体问题 2总体分析3模型假设4符号说明&#xff08;等四问全部更新完再写&#xff09;5模型的建立与求解5.1问题一模型的建立与求解5.1.1问题的具体分析5.1.2模型的准备 目前B题第一问的详细求解过程以及对应论文部分已经完成&#xff…

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中…

【网络安全】Exif 数据储存型XSS

未经许可,不得转载。 文章目录 Exif步骤Exif EXIF(Exchangeable Image File Format)数据是一种存储在图像文件中的元数据格式,常用于数码照片和扫描图像。它包含了与图像相关的各种信息,比如拍摄日期和时间、相机品牌和型号、拍摄时的设置(如曝光时间、光圈、ISO等)、地…

Java Kafka生产者实现

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

Android 9.0 SystemUI状态栏/快捷设置介绍

Android 9.0 SystemUI状态栏/快捷设置介绍 状态栏 状态栏是SystemUI里的重要功能之一&#xff0c;状态栏的一大功能就是显示功能图标&#xff0c;以告知用户一些最基本的信息状态&#xff0c;在 Android 9.0 版本中&#xff0c;状态栏一般包含运营商信息、时间、日期、电池、通…

python简单计算入门教程|加减法

python通过调用numpy模块&#xff0c;非常擅长数学计算。再通过调用matplotlib模块&#xff0c;可以自由自在地输出numpy计算的结果。 今天&#xff0c;我们就尝试一些基本计算。 下述是正弦函数和余弦函数的加法和减法计算结果。 图1 代码为&#xff1a; import matplotli…

UE4_后期处理_后期处理材质及后期处理体积三—遮挡物体描边显示

一、效果&#xff1a; 在很多游戏中为了玩家能看到墙面背后是否有敌人&#xff0c;会给被遮挡的敌人增加描边显示&#xff0c;效果如下&#xff1a; 参考&#xff1a; https://zhuanlan.zhihu.com/p/81310476 https://zhuanlan.zhihu.com/p/358140547 二、所需知识 知识点…

3.C_数据结构_栈

概述 什么是栈&#xff1a; 栈又称堆栈&#xff0c;是限定在一段进行插入和删除操作的线性表。具有后进先出(LIFO)的特点。 相关名词&#xff1a; 栈顶&#xff1a;允许操作的一端栈底&#xff1a;不允许操作的一端空栈&#xff1a;没有元素的栈 栈的作用&#xff1a; 可…

如何在 Linux 系统中禁用用户登录 ?

管理 Linux 系统上的帐户是系统管理员的一项重要任务。一个常见的任务是禁用帐户&#xff0c;由于各种原因可能需要禁用帐户&#xff0c;例如当员工离开公司或出于安全目的需要临时禁用访问时。 本指南将以简单易懂的步骤引导您完成在 Linux 系统上禁用帐户的过程。 Step 1: …

2024.9.8

打了一上午又一下午的比赛 DABOI Round 1 【MX-X3】梦熊周赛 未来组 3 & RiOI Round 4 第一场还好&#xff0c;共得180pts 难度比较合理&#xff0c;偏向正常noip 然后就发现自己计数问题很难做到推广思路&#xff0c;只会部分分 梦熊的模拟赛就抽象了 题目难度夸大…

IDEA安装教程配置java环境(超详细)

引言 IntelliJ IDEA 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛用于 Java 开发&#xff0c;但也支持多种编程语言&#xff0c;如 Kotlin、Groovy 和 Scala。本文将为你提供一步一步的指南&#xff0c;帮助你在 Windows 系统上顺利安装 Intelli…

Qt:解决player->duration()第一次获取媒体时长为0的问题

前言 最近想做一个白噪声播放器&#xff0c;中间就用到了QMediaplayer这个类&#xff0c;其中遇到两个问题&#xff0c;一个是未初始化好就调用player->state()导致程序异常崩溃的问题(这个问题留到下一个文章去说)&#xff1b;还有一个就是调用player->duration()第一次…

Mendix 创客访谈录|Mendix赋能汽车零部件行业:重塑架构,加速实践与数字化转型

在当前快速发展的技术时代&#xff0c;汽车行业正经历着前所未有的数字化转型。全球领先的汽车零配件制造商面临着如何利用最新的数字技术优化其制造车间管理的挑战。从设备主数据管理到生产执行工单管理&#xff0c;再到实时监控产量及能耗&#xff0c;需要一个灵活、快速且高…

基于单片机智能电源插座设计

本设计基于单片机智能电源插座设计&#xff0c;该系统主要包括&#xff1a;单片机、WIFI模块、显示模块、继电器模块、按键输入模块、功率检测模块及手机APP&#xff0c;实现对用电量的实时监测的功能。功率检测模块实时测量用电器的供电电压、电流、功率&#xff1b;按键输入模…

微信小程序:navigateTo跳转无效

关于 navigateTo 跳转无效问题&#xff0c;在IOS、模拟器上面都能正常跳转&#xff0c;但是在安卓上面不能跳转&#xff0c;过了一段时间IOS也不能跳转了。仔细找了下问题结果是要跳转的页面是tab&#xff0c;不能使用navigateTo 取跳转修改为&#xff1a; wx.switchTab({url:…

经验笔记:跨站脚本攻击(Cross-Site Scripting,简称XSS)

跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;简称XSS&#xff09;经验笔记 跨站脚本攻击&#xff08;XSS&#xff1a;Cross-Site Scripting&#xff09;是一种常见的Web应用程序安全漏洞&#xff0c;它允许攻击者将恶意脚本注入到看起来来自可信网站的网页上。当…

Spring Boot集成PDFBox实现电子签章

概述 随着无纸化办公的普及&#xff0c;电子文档的使用越来越广泛。电子签章作为一种有效的身份验证方式&#xff0c;在很多场景下替代了传统的纸质文件签名。Apache PDFBox 是一个开源的Java库&#xff0c;可以用来渲染、生成、填写PDF文档等操作。本文将介绍如何使用Spring …

Socket编程 (连接,发送消息) (Tcp、Udp) - Part1

Socket编程 (连接,发送消息) (Tcp、Udp) 本篇文章主要实现Socket在Tcp\Udp协议下相互通讯的方式。(服务器端与客户端的通讯) 1.基于Tcp协议的Socket通讯类似于B/S架构&#xff0c;面向连接&#xff0c;但不同的是服务器端可以向客户端主动推送消息。 使用Tcp协议通讯需要具备…

HiveServer2 启动时 datanucleus.schema.autoCreateTables 不生效的问题

HiveServer2 启动时出 "Either your MetaData is incorrect, or you need to enable "datanucleus.schema.autoCreateTables"问题 Required table missing : "FUNCS" in Catalog "" Schema "". DataNucleus requires this table…

深入探索Go语言中的指针:内存操作的艺术

首先&#xff0c;尽管指针&#xff08;pointer&#xff09;和switch语句在概念上并无直接联系&#xff0c;但本文将它们并置讨论的原因在于&#xff1a;这两个编程概念在实际学习和应用过程中常被编程人员所忽视。 对于指针的使用&#xff0c;初学者往往因其概念的抽象性和操作…