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

算法入门-贪心1

第八部分:贪心

409.最长回文串(简单)

给定一个包含大写字母和小写字母的字符串 s ,返回通过这些字母构造成的最长的回文串 的长度。

在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。

示例 1:

输入:s = "abccccdd"
输出:7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

示例 2:

输入:s = "a"
输出:1
解释:可以构造的最长回文串是"a",它的长度是 1。

第一种思路:

看到这种需要统计数量的,不自然的会想到使用字典的数据结构,按照这种思路,我考虑如下:

  1. 空字符串检查

  • 首先检查输入字符串 s 是否为空。如果为空,直接返回0,因为没有字符可以构成回文串。

  1. 字符计数

  • 使用一个 HashMap 来统计字符串中每个字符的出现次数。遍历字符串中的每个字符,更新其在 map 中的计数。

  1. 计算回文串长度

  • 初始化 sum 为0,用于存储可以构成的最长回文串的长度。

  • 遍历map中的每个字符及其出现次数:

    • 如果出现次数是偶数,则可以完全加入到回文串中,直接加到 sum

    • 如果出现次数是奇数,则将其减一后加入到 sum,并标记存在奇数值的键,以便后续可以在回文串的中心添加一个字符。

  1. 中心字符处理

  • 如果存在奇数值的键,说明可以在回文串的中心添加一个字符,因此在 sum 上加1。

  1. 返回结果

  • 最后返回 sum,即为通过给定字符串构造的最长回文串的长度。

import java.util.HashMap;  
import java.util.Map;  class Solution {  public int longestPalindrome(String s) {  // 检查字符串是否为空  if (s.length() == 0) {  return 0; // 如果字符串为空,直接返回0  }  int sum = 0; // 用于存储可以构成的最长回文串的长度  boolean hasOddValue = false; // 用于跟踪是否存在奇数值的键  Map<Character, Integer> map = new HashMap<>(); // 创建一个HashMap来存储字符及其出现次数  // 遍历字符串中的每个字符  for (char ch : s.toCharArray()) {  // 更新字符的出现次数  map.put(ch, map.getOrDefault(ch, 0) + 1);  }  // 遍历字符计数的映射  for (Map.Entry<Character, Integer> entry : map.entrySet()) {  int value = entry.getValue(); // 获取当前字符的出现次数  if (value % 2 == 0) { // 如果出现次数是偶数  sum += value; // 偶数部分可以完全加入到回文串中  } else { // 如果出现次数是奇数  sum += (value - 1); // 奇数部分减一后加入到回文串中  hasOddValue = true; // 标记存在奇数值的键  }  }  // 如果存在奇数值的键,则可以在回文串的中心添加一个字符  if (hasOddValue) {  sum += 1; // 增加1以考虑中心字符  }  return sum; // 返回计算得到的最长回文串长度  }  // 辅助方法:检查字符串中的所有字符是否相同  private boolean allCharactersSame(String s) {  char firstChar = s.charAt(0); // 获取第一个字符  for (int i = 1; i < s.length(); i++) {  if (s.charAt(i) != firstChar) {  return false; // 如果发现不同的字符,返回false  }  }  return true; // 所有字符相同,返回true  }  
}

第二种思路: 采用官方的贪心思路(不管我暂时还没有从官方的解释中体会到贪心体现在哪里)

解释:那么我们如何通过给定的字符构造一个回文串呢?我们可以将每个字符使用偶数次,使得它们根据回文中心对称。在这之后,如果有剩余的字符,我们可以再取出一个,作为回文中心。

于每个字符 ch,假设它出现了 v 次,我们可以使用该字符 v / 2 * 2 次,在回文串的左侧和右侧分别放置 v / 2 个字符 ch,其中 / 为整数除法。例如若 "a" 出现了 5 次,那么我们可以使用 "a" 的次数为 4,回文串的左右两侧分别放置 2 个 "a"。

如果有任何一个字符 ch 的出现次数 v 为奇数(即 v % 2 == 1),那么可以将这个字符作为回文中心,注意只能最多有一个字符作为回文中心。在代码中,我们用 ans 存储回文串的长度,由于在遍历字符时,ans 每次会增加 v / 2 * 2,因此 ans 一直为偶数。但在发现了第一个出现次数为奇数的字符后,我们将 ans 增加 1,这样 ans 变为奇数,在后面发现其它出现奇数次的字符时,我们就不改变 ans 的值了。

详情见:409. 最长回文串 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/longest-palindrome/

  1. 字符计数

    • 使用一个长度为128的数组 count 来统计字符串中每个字符的出现次数。数组的索引对应字符的ASCII值。

    • 遍历字符串 s,对于每个字符 c,增加 count[c] 的值。

  2. 计算回文串长度

    • 初始化 ans 为0,用于存储可以构成的最长回文串的长度。

    • 遍历count数组,对于每个字符的出现次数v:

      • 使用 v / 2 * 2 计算出可以组成的偶数部分,并加到 ans 中。这样可以确保回文串的左右两边是对称的。

      • 如果 v 是奇数,并且当前的 ans 是偶数,说明可以在回文串的中心添加一个字符(即使得回文串的长度增加1),因此将 ans 加1。

  3. 返回结果

    • 最后返回 ans,即为通过给定字符串构造的最长回文串的长度。

class Solution {  public int longestPalindrome(String s) {  // 创建一个长度为128的数组,用于统计字符的出现次数  int[] count = new int[128];  int length = s.length();  // 遍历字符串,统计每个字符的出现次数  for (int i = 0; i < length; ++i) {  char c = s.charAt(i);  count[c]++; // 增加字符c的计数  }  int ans = 0; // 用于存储最长回文串的长度  // 遍历计数数组,计算可以构成的回文串长度  for (int v : count) {  ans += v / 2 * 2; // 将偶数部分直接加到ans中  // 如果当前字符的出现次数为奇数,并且ans是偶数,则可以加1  if (v % 2 == 1 && ans % 2 == 0) {  ans++; // 可以在回文串的中心添加一个字符  }  }  return ans; // 返回计算得到的最长回文串长度  }  
}

455.分发饼干(简单)

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

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

示例 1:

输入: g = [1,2,3], s = [1,1]
输出: 1
解释: 
你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。
所以你应该输出 1。

示例 2:

输入: g = [1,2], s = [1,2,3]
输出: 2
解释: 
你有两个孩子和三块小饼干,2 个孩子的胃口值分别是 1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出 2。

第一种思路: 首先采用之前刷题的经验,先把这两个数组进行排序,减少工作量。

然后使用双指针的方法遍历两个数组,避免双重循环。

具体而言:

  1. 排序:首先对孩子的胃口数组 g 和饼干的大小数组 s 进行排序。这是为了能够从最小的胃口和最小的饼干开始进行比较,确保尽可能多的孩子能够得到满足。

  2. 双指针法:使用两个指针 childIndexcookieIndex 分别指向孩子和饼干的当前索引。childIndex 用于遍历孩子,cookieIndex 用于遍历饼干。

  3. 满足条件

    • 如果当前饼干可以满足当前孩子的胃口,即 g[childIndex] <= s[cookieIndex],则增加满足的孩子计数 contentChildrenCount,并同时移动到下一个孩子和下一个饼干。

    • 如果当前饼干不能满足当前孩子,则只移动到下一个饼干,继续尝试满足当前孩子。

  4. 结束条件:当遍历完所有孩子或所有饼干时,循环结束,返回满足的孩子数量。

class Solution {  public int findContentChildren(int[] g, int[] s) {  // 对孩子的胃口和饼干的大小进行排序  Arrays.sort(g);  Arrays.sort(s);  int contentChildrenCount = 0; // 记录满足的孩子数量  int childIndex = 0; // 当前孩子的索引  int cookieIndex = 0; // 当前饼干的索引  // 遍历孩子和饼干,直到其中一个数组遍历完  while (childIndex < g.length && cookieIndex < s.length) {  // 如果当前饼干可以满足当前孩子的胃口  if (g[childIndex] <= s[cookieIndex]) {  contentChildrenCount++; // 满足一个孩子  childIndex++; // 移动到下一个孩子  }  // 无论饼干是否满足孩子,都要移动到下一个饼干  cookieIndex++;  }  return contentChildrenCount; // 返回满足的孩子数量  }  
}

后面发现官方的解答和我类似,但是他就是使用双重循环的,想了一下。

贪心算法的贪心在这里面体现在哪?

在这个问题中,贪心算法的贪心策略体现在以下几个方面:

  1. 局部最优选择

    • 每次选择当前最小的饼干来满足当前最小的孩子的胃口。这种选择是基于局部最优的原则,即在每一步中都选择能够立即满足当前孩子的最小饼干。通过这种方式,尽可能多的孩子能够得到满足。

  2. 排序

    • 通过对孩子的胃口和饼干的大小进行排序,确保我们可以从最小的开始进行比较。这种排序使得我们能够有效地找到最小的满足条件的饼干,从而实现贪心选择。

  3. 不回溯

    • 一旦选择了一个饼干来满足一个孩子,就不会回头去尝试用这个饼干去满足其他孩子。每次都向前推进,确保每个孩子都尽可能得到满足,而不去重新考虑之前的选择。

  4. 全局最优解的构建

    • 通过不断地做出局部最优选择(即用当前最小的饼干满足当前最小的孩子),最终构建出全局最优解(即最大数量的孩子得到满足)。这种策略在许多贪心算法中都是常见的。

总结

贪心算法在这个问题中的核心思想是通过局部最优选择(最小饼干满足最小胃口)来达到全局最优解(最大数量的孩子得到满足)。这种方法简单高效,适合解决此类问题。

相关文章:

算法入门-贪心1

第八部分&#xff1a;贪心 409.最长回文串&#xff08;简单&#xff09; 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回通过这些字母构造成的最长的回文串 的长度。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串…...

element-plus的面包屑组件el-breadcrumb

面包屑组件主要用来显示当页面路径&#xff0c;以及快速返回之前的页面。 涉及2个组件 el-breadcrumb 和el-breadcrumb-item, el-breadcrumb的spearator指定item的分隔符 el-breadcrumb-item的to和replace属性和vue-router的一致&#xff0c;需要结合vue_router一起使用 用法…...

推荐几个网盘资源站给大伙,找资源更方便

夸克网盘在当前已然成为极为主流的网盘之一&#xff0c;其功能体验堪称强大&#xff0c;不仅支持在线解压阅读&#xff0c;磁力离线等功能也十分出色。那么&#xff0c;究竟该如何寻找夸克资源呢&#xff1f;下面&#xff0c;我就来为大家分享几个堪称神级的夸克资源网站。 一、…...

【Qt】Qml界面中嵌入C++ Widget窗口

1. 目的 qml做出的界面漂亮&#xff0c;但是执行效率低&#xff0c;一直想找一个方法实现qml中嵌入c界面。现在从网上找到一个方法&#xff0c;简单试了一下貌似可行&#xff0c;分享一下。 2. 显示效果 3. 代码 3.1 工程结构 3.2 pro文件 需要添加widgets > QT quick …...

Python快速入门 —— 第五节:接口开发

第五节:接口开发 目标: 学习使用Flask框架开发简单的Web接口,实现对学生信息的增删改查,通过HTTP请求与应用交互。 内容: Flask简介: Flask是一个轻量级的Python Web框架,使用简单,扩展性强,适合快速开发Web应用。安装Flask: pip install flask创建Flask应用: fr…...

利用secureCRT向虚拟机发送文件(secureCRT安装使用教程)

链接: secureCRT 链接:https://pan.baidu.com/s/1CvNYzoBbLVkyYNFq7hrT0g 提取码:5974 链接: secureCRT安装使用教程 链接:https://pan.baidu.com/s/1Bbi7SqyJBere8G53BCYL5A 提取码:xjw1...

AI杂七杂八系列(1)——工程篇

1. 远程服务器无法登录问题 2. 内存溢出解决方法 3. Padding 4. try...except...处理异常报错 5. view、expand、repeat、transpose、permute和squeeze、unsqueeze的区别 1. 远程服务器无法登录问题 权限可能是root权限&#xff0c;修改权限 用户权限&#xff1a; sudo c…...

学习大数据DAY58 增量抽取数据表

作业 1 SQL 优化的常见写法有哪些 - 面试经常被问 使用索引&#xff1a;合理创建和使用索引是提高查询效率的关键。索引可以加速数据的检 索速度&#xff0c;但是索引也会占用额外的存储空间&#xff0c;并且在插入、删除和更新操作时会 有额外的开销。 避免全表扫描&…...

HTTPTomcat

HTTP&Tomcat&Servlet 今日目标&#xff1a; 了解JavaWeb开发的技术栈理解HTTP协议和HTTP请求与响应数据的格式掌握Tomcat的使用掌握在IDEA中使用Tomcat插件 1&#xff0c;Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网&#xff0c;也称为万维网(www)&#xff0c;…...

Python数据分析-Matplotlib快速入门

一、pyplot 二、绘图 1.绘制x和y的点 2.无线绘图 3.多点 4.默认x点 三、标记 1.标记 2.参考 3.格式化字符串 4.尺寸 5.颜色 四、线条 1.线形 两个都是设置虚线 2.更短的语法 3.线参考 4.线条颜色 5.线宽度 6.多条线 也可以 五、标签 1.为绘图创建标签 2.为绘图设置标题 3…...

重塑在线软件开发新纪元:集成高效安全特性,深度解析与评估支持浏览器在线编程的系统架构设计

目录 案例 【题目】 【问题 1】(13 分) 【问题 2】(12 分) 【答案】 【问题 1】解析 【问题 2】解析 相关推荐 案例 阅读以下关于软件架构设计与评估的叙述&#xff0c;回答问题1和问题2。 【题目】 某公司拟开发一套在线软件开发系统&#xff0c;支持用户通过浏览器…...

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】003 - vmlinux.lds 链接脚本文件源码分析

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】003 - vmlinux.lds 链接脚本文件源码分析 系列文章汇总:《鸿蒙OH-v5.0源码分析之 Uboot+Kernel 部分】000 - 文章链接汇总》 本文链接:《【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】003 - vmlinux.lds 链接脚本文件源码分析》 …...

MongoDB实现高级RAG:Parent-Document检索技术详解

MongoDB实现高级RAG&#xff1a;Parent-Document检索技术详解 引言 在人工智能和自然语言处理领域&#xff0c;检索增强生成(Retrieval-Augmented Generation, RAG)技术正在迅速发展。本文将介绍一种更高级的RAG实现方式&#xff1a;Parent-Document检索。我们将探讨如何使用…...

胡学乱想----前端知识点(css色彩)

1. margin 属性 简写 margin 属性有两个值时,它将 margin-top 和 margin-bottom 设置为第一个值,并将 margin-left 和 margin-right 设置为第二个值 .marker {width: 200px;height: 25px;background-color: red;margin: 10px auto; }2. rgb 属性 CSS 的 rgb 函数接收红色…...

GEE 案例——利用MODIS数据和NDWI指数进行美国五大湖水体计算和时序分析(直方图统计和面积统计)

目录 简介 MODIS数据 代码 结果 简介 利用MODIS数据和NDWI指数进行水体计算和时序分析(直方图统计和面积统计),这里我们统计了2001-2023年的美国五大湖的水域面积变化情况。 MODIS数据 MODIS/061/MOD09A1数据是由美国宇航局(NASA)的Moderate Resolution Imaging Spe…...

【jvm】记一次hive堆heap内存溢出的排查

先看下java的内存模型 监控jvm工具&#xff1a;visualVM 摘录一下内容&#xff1a; 由c开发的jvm&#xff0c;它巧妙地设计了java的设计理念——即万物皆对象。并设计了这些对象应该如何存储&#xff0c;如何调用&#xff0c;并通过不断迭代设计让对象的存储和回收&#xff0…...

编译运行 webAssembly(wasm)

环境准备&#xff1a; lunix下docker 参考https://hub.docker.com/r/emscripten/emsdk 拉编译环境 docker pull emscripten/emsdk 编译 随便找个目录&#xff0c;敲下面命令&#xff0c;编译一个webAssembly 程序 # create helloworld.cpp cat << EOF > hellowo…...

Linux bash 关联数组

目录 一. 关联数组定义二. 访问关联数组三. 元素的添加与删除四. 键值对的获取与遍历五. 实际应用5.1 读取封装配置文件内容5.2 收集系统信息 一. 关联数组定义 从 Bash 4.0 开始&#xff0c;Bash 支持关联数组。关联数组允许你将键和值配对&#xff0c;并通过键来访问值&…...

选择排序

一&#xff1a;基本思想 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完 。 解释&#xff1a;就是不断的找到最小的放在最左面&#xff0c;然后缩短数组&#xff0c;…...

SQL数据库(MySQL)

一、在Ubuntu系统下安装MySQL数据库 1、更新软件源&#xff0c;在确保ubuntu系统能正常上网的情况下执行以下命令 sudo apt-get update 2、安装MySQL数据库及相关软件包 # 安装过程中设置root用户的密码 123456 sudo apt-get install mysql-server ​ # 安装访问数据库的客…...

开源技术驱动下的上市公司财务主数据管理实践

开源技术驱动下的上市公司财务主数据管理实践 —— 以人造板制造业为例 引言&#xff1a;财务主数据的战略价值与行业挑战 在资本市场监管日益严格与企业数字化转型的双重驱动下&#xff0c;财务主数据已成为上市公司财务治理的核心基础设施。对于人造板制造业而言&#xff0…...

hadoop集群datanode启动显示init failed,不能解析hostname

三个datanode集群&#xff0c;有一个总是起不起来。去查看log显示 Initialization failed for Block pool BP-1920852191-192.168.115.154-1749093939738 (Datanode Uuid 89d9df36-1c01-4f22-9905-517fee205a8e) service to node154/192.168.115.154:8020 Datanode denied com…...

每日Prompt:双重曝光

提示词 新中式&#xff0c;这幅图像将人体头像轮廓与山水中式建筑融为一体&#xff0c;双重曝光&#xff0c;体现了反思、内心平静以及人与自然相互联系的主题&#xff0c;靛蓝&#xff0c;水墨画&#xff0c;晕染&#xff0c;极简...

如何把 Mac Finder 用得更顺手?——高效文件管理定制指南

系统梳理提升 Mac Finder 体验的实用设置与技巧&#xff0c;助你用更高效的方式管理文件。文末引出进阶选择 Path Finder。 阅读原文请转到&#xff1a;https://jimmysong.io/blog/customize-finder-for-efficiency/ 作为一个用 Mac 多年的用户&#xff0c;我始终觉得 Finder 虽…...

【EF Core】 EF Core并发控制:乐观锁与悲观锁的应用

文章目录 前言一、并发的风险二、EF Core中的并发控制方式2.1 开放式并发&#xff08;乐观锁&#xff09;2.1.1 应用程序管理的属性并发令牌2.1.2 数据库生成的并发令牌 2.2 悲观锁 总结 前言 实际的生产环境中&#xff0c;我们经常能遇到数据库由多个应用程序同时使用。每个程…...

9.axios底层原理,和promise的对比(2)

&#x1f63a;&#x1f63a;&#x1f63a; 和promise的对比 完全可以直接使用 Promise 来发 HTTP 请求&#xff0c;比如用原生 fetch Promise 就可以实现网络请求功能&#x1f447; ✅ 用 Promise fetch 的写法&#xff08;原生&#xff09; fetch(‘https://api.example.c…...

手机号在网状态查询接口如何用PHP实现调用?

一、什么是手机号在网状态查询接口 通过精准探测手机号的状态&#xff0c;帮助平台减少此类问题的发生&#xff0c;提供更个性化的服务或进行地域性营销 二、应用场景 1. 金融风控 通过运营商在网态查询接口&#xff0c;金融机构可以核验贷款申请人的手机状态&#xff0c;拦…...

【LRU】 (最近最少使用)

LRU (最近最少使用) 文章目录 LRU (最近最少使用)一、LRU是什么&#xff1f;二、实现1.常规算法2.双栈更替总结 一、LRU是什么&#xff1f; LRU&#xff08;Least Recently Used&#xff09;是一种常见的缓存淘汰策略&#xff0c;核心思想是 “淘汰最长时间未被使用的缓存数据…...

Vue3学习(4)- computed的使用

1. 简述与使用 作用&#xff1a;computed 用于基于响应式数据派生出新值&#xff0c;其值会自动缓存并在依赖变化时更新。 ​缓存机制​&#xff1a;依赖未变化时直接返回缓存值&#xff0c;避免重复计算&#xff08;通过 _dirty 标志位实现&#xff09;。​响应式更新​&…...

Kafka 入门指南与一键部署

Kafka 介绍 想象一下你正在运营一个大型电商平台&#xff0c;每秒都有成千上万的用户浏览商品、下单、支付&#xff0c;同时后台系统还在记录用户行为、更新库存、处理物流信息。这些海量、持续产生的数据就像奔腾不息的河流&#xff0c;你需要一个强大、可靠且实时的系统来接…...