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

关联子串 - 华为OD统一考试(JavaScript题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。

看不懂有疑问需要答疑辅导欢迎私VX: code5bug

华为OD机试真题

题目描述

给定两个字符串str1和str2,如果字符串str1中的字符,经过排列组合后的字符串中,只要有一个字符串是str2的子串,则认为str1是str2的关联子串。

若str1是str2的关联子串,请返回子串在str2的起始位置;

若不是关联子串,则返回-1。

输入描述

输入两个字符串,分别为题目中描述的str1、str2。

备注:

输入的字符串只包含小写字母;
两个字符串的长度范围[1, 100000]之间;

输出描述

若str1是str2的关联子串,请返回子串在str2的起始位置;

若不是关联子串,则返回-1。

若str2中有多个str1的组合子串,请返回最小的起始位置。

示例1

输入:
abc efghicbaiii输出:
5说明:
str2包含str1的一种排列组合(“cab”),此组合在str2的字符串起始位置为5(从0开始计数)

示例2

输入:
abc efghiccaiii输出:
-1说明:
“abc”字符串中三个字母的各种组合(abc、acb、bac、bca、cab、cba),str2中均不包含,因此返回-1

题解

我们需要判断字符串 str1 的任意排列是否是 str2 的子串。如果是,返回该子串在 str2 中的起始位置(最小位置);否则返回 -1。

解题思路

  1. 滑动窗口法:这是解决此类问题的经典方法。
    • 统计 str1 的字符频率。
    • str2 上维护一个与 str1 长度相同的滑动窗口。
    • 比较窗口内字符频率与 str1 的字符频率。
    • 如果匹配,返回当前窗口的起始位置;否则滑动窗口继续检查。

JavaScript

const rl = require('readline').createInterface({input: process.stdin,output: process.stdout,
});var iter = rl[Symbol.asyncIterator]();const readline = async () => (await iter.next()).value;// 在s2中查找与s1字符组成相同的子串(关联子串)的起始位置
function solve(s1, s2) {// 使用Map统计s1的字符频率const cnt1 = new Map();for (const c of s1) {cnt1.set(c, (cnt1.get(c) || 0) + 1);}const targetLen = s1.length;if (targetLen > s2.length) return -1;// 初始化滑动窗口(前targetLen个字符)const window = new Map();for (let i = 0; i < targetLen; i++) {const c = s2[i];window.set(c, (window.get(c) || 0) + 1);}// 检查初始窗口是否匹配if (compareMaps(cnt1, window)) {return 0;}// 滑动窗口遍历s2for (let i = targetLen; i < s2.length; i++) {// 移除窗口最左边的字符const leftChar = s2[i - targetLen];if (window.get(leftChar) === 1) {window.delete(leftChar);} else {window.set(leftChar, window.get(leftChar) - 1);}// 添加新进入窗口的字符const rightChar = s2[i];window.set(rightChar, (window.get(rightChar) || 0) + 1);// 检查当前窗口是否匹配if (compareMaps(cnt1, window)) {return i - targetLen + 1;}}return -1; // 未找到匹配子串
}// 比较两个Map是否相等(用于频率统计比较)
function compareMaps(map1, map2) {if (map1.size !== map2.size) return false;for (const [key, val] of map1) {if (map2.get(key) !== val) {return false;}}return true;
}// Author: code5bug
(async () => {const input = await readline();const [s1, s2] = input.trim().split(/\s+/);console.log(solve(s1, s2));rl.close();
})();

希望这个专栏能让您熟练掌握算法
整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

相关文章:

  • 姜老师MBTI课程:4条轴线的总结
  • ssh连接断开,保持任务后台执行——tmux
  • Java 中 Redis 过期策略深度解析(含拓展-redis内存淘汰策略列举)
  • spring boot项目中的一些常用提示信息
  • C++17新特性 Lambda表达式
  • 第十四篇:MySQL 运维中的故障场景还原与排查实战技巧
  • NLP基础:从词嵌入到预训练模型应用
  • token
  • 进程间通信(消息队列)
  • C++学习打卡
  • qwen3解读
  • Redis事务详解:原理、使用与注意事项
  • vue-09(使用自定义事件和作用域插槽构建可重用组件)
  • 磨皮功能 C++/C的OpenCV 实现
  • 【11408学习记录】考研英语写作提分秘籍:2013真题邀请信精讲+万能模板套用技巧
  • 【shell】通过Shell命令占用内存
  • 利用python工具you-get下载网页的视频文件
  • #AI短视频制作完整教程
  • JDK21深度解密 Day 9:响应式编程模型重构
  • CTFHub-RCE 命令注入-过滤目录分隔符
  • wordpress采集文章自动翻译/太原百度seo排名软件
  • eclipse做网站代码/如何百度推广
  • 建设电瓶车官方网站/在线crm系统
  • 网页欣赏网站/网站页面优化内容包括哪些
  • 如何学习网站开发编程/新闻热点事件2021(最新)
  • 网站建设企业云市场/今日头条最新新闻消息