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

力扣(leetcode)每日一题 2516 每种字符至少取 K 个 | 滑动窗口

2516. 每种字符至少取 K 个

给你一个由字符 'a''b''c' 组成的字符串 s 和一个非负整数 k 。每分钟,你可以选择取走 s 最左侧 还是 最右侧 的那个字符。

你必须取走每种字符 至少 k 个,返回需要的 最少 分钟数;如果无法取到,则返回 -1

示例 1:

**输入:**s = “aabaaaacaabc”, k = 2
**输出:**8
解释:
从 s 的左侧取三个字符,现在共取到两个字符 ‘a’ 、一个字符 ‘b’ 。
从 s 的右侧取五个字符,现在共取到四个字符 ‘a’ 、两个字符 ‘b’ 和两个字符 ‘c’ 。
共需要 3 + 5 = 8 分钟。
可以证明需要的最少分钟数是 8 。

示例 2:

**输入:**s = “a”, k = 1
输出:-1
**解释:**无法取到一个字符 ‘b’ 或者 ‘c’,所以返回 -1 。

提示:

  • 1 <= s.length <= 105
  • s 仅由字母 'a''b''c' 组成
  • 0 <= k <= s.length
题解

这里可以想到滑动窗口的变种。我左边一个指针,右边一个指针。左边的先顶到满足的最右边,然后右边顶向左边的同时,左边的指针可以弹出来
这个过程中不断刷新最小值


public static int takeCharacters(String s, int k) {  // 变相滑动窗口  int[] count = new int[3];  char[] charArray = s.toCharArray();  int index = 0;  int length = charArray.length;  for (int i = 0; i < length; i++) {  if (!verify(count, k)) {  if (charArray[i] == 'a') {  count[0]++;  } else if (charArray[i] == 'b') {  count[1]++;  } else if (charArray[i] == 'c') {  count[2]++;  }  index++;  } else {  break;  }  }  if (!verify(count, k)) {  return -1;  }  int res = index;// 个数  int rightIndex = 0;  for (int i = length - 1; i > 0 && index > 0 && rightIndex < res; i--) {  rightIndex++;  if (charArray[i] == 'a') {  count[0]++;  } else if (charArray[i] == 'b') {  count[1]++;  } else if (charArray[i] == 'c') {  count[2]++;  }  // 先加上最后面一位,然后弹出index的位数  while (verify(count, k) && index > 0) {  index--;  if (charArray[index] == 'a') {  count[0]--;  } else if (charArray[index] == 'b') {  count[1]--;  } else if (charArray[index] == 'c') {  count[2]--;  }  }  // 如果还是满足,就不需要加一  if (verify(count, k)) {  res = Math.min(res, index + rightIndex);  } else {  res = Math.min(res, index + rightIndex + 1);  }  }  return res;  
}  public static boolean verify(int[] count, int k) {  return count[0] >= k && count[1] >= k && count[2] >= k;  
}

这里index就是左边的个数,leftIndex就是右边的个数。单独命名代码好写点。
退出语句皆是下 i > 0 && index > 0 && rightIndex < res i一定要大于0不说了,index如果是0,说明左指针已经弹完了,就可以退出了,还有如果右指针弹入的数量比刷新的值还大,也没有继续的意义了

这里的if是可以优化的

public static int takeCharacters2(String s, int k) {  // 变相滑动窗口  int[] count = new int[3];  char[] charArray = s.toCharArray();  int index = 0;  int length = charArray.length;  for (int i = 0; i < length; i++) {  if (!verify(count, k)) {  count[charArray[i] - 'a']++;  index++;  } else {  //index--;// 到了4更新  然后来到5发现成功了,其实index在4的时候已经成功了 这里减去1  break;  }  }  if (!verify(count, k)) {  return -1;  }  int res = index;// 个数  int rightIndex = 0;  for (int i = length - 1; i > 0 && index > 0 && rightIndex < res; i--) {  rightIndex++;  count[charArray[i] - 'a']++;  // 先加上最后面一位,然后弹出index的位数  while (verify(count, k) && index > 0) {  index--;  count[charArray[index] - 'a']--;  }  // 如果还是满足,就不需要加一  if (verify(count, k)) {  res = Math.min(res, index + rightIndex);  } else {  res = Math.min(res, index + rightIndex + 1);  }  }  return res;  
}public static boolean verify(int[] count, int k) {  return count[0] >= k && count[1] >= k && count[2] >= k;  
}  
总结

其实滑动窗口的代码并不好写,涉及到临界的判断。如果是第一次写,很可能会自闭。我已经写过很多次了,还是不能一笔写完

请添加图片描述

这里花了这么多时间是想着把index和rightIndex融入到for循环。
然后这个忘记写了

 // 如果还是满足,就不需要加一  if (verify(count, k)) {  res = Math.min(res, index + rightIndex);  } else {  res = Math.min(res, index + rightIndex + 1);  }  

请添加图片描述

这不是最优解,但是最近比较忙,就不研究最优解了

相关文章:

  • 【项目经验分享】深度学习自然语言处理技术毕业设计项目案例定制
  • 学生信息管理系统开发实战:掌握多数据模型关联关系的设计和使用
  • 「iOS」——KVC
  • 使用 pypdf 给 PDF 添加目录书签
  • 搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(四)-搜索
  • 基于Hive和Hadoop的图书分析系统
  • nodejs逐字读取文件示例
  • 防火墙详解(三)华为防火墙基础安全策略配置(命令行配置)
  • 如何恢复被删除的 GitLab 项目?
  • 前端Vue.js与后端Flask/Django协同开发指南
  • 修改DNS地址有什么影响
  • 选择更轻松:山海鲸可视化与PowerBI的深度对比
  • RP2040 C SDK GPIO和IRQ 唤醒功能使用
  • Angular与Vue的全方位对比分析
  • uni-app 封装websocket 心跳检测,开箱即用
  • [deviceone开发]-do_Webview的基本示例
  • 《深入 React 技术栈》
  • 345-反转字符串中的元音字母
  • Android Studio:GIT提交项目到远程仓库
  • Angular6错误 Service: No provider for Renderer2
  • chrome扩展demo1-小时钟
  • HomeBrew常规使用教程
  • JavaScript标准库系列——Math对象和Date对象(二)
  • PHP面试之三:MySQL数据库
  • vuex 笔记整理
  • Webpack 4 学习01(基础配置)
  • yii2中session跨域名的问题
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 数据科学 第 3 章 11 字符串处理
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 中文输入法与React文本输入框的问题与解决方案
  • 7行Python代码的人脸识别
  • ​linux启动进程的方式
  • ​插件化DPI在商用WIFI中的价值
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • #define,static,const,三种常量的区别
  • #mysql 8.0 踩坑日记
  • $GOPATH/go.mod exists but should not goland
  • (145)光线追踪距离场柔和阴影
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (SERIES10)DM逻辑备份还原
  • (附源码)ssm码农论坛 毕业设计 231126
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (十六)串口UART
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (译)2019年前端性能优化清单 — 下篇
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)JAVA中的堆栈
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET MAUI Sqlite数据库操作(二)异步初始化方法
  • .NET/C# 的字符串暂存池