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

LeetCode 热题 100——滑动窗口——找到字符串中所有字母异位词

8. 找到字符串中所有字母异位词

题目描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:

输入: s = “cbaebabacd”, p = “abc”
输出: [0,6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的异位词。
示例 2:

输入: s = “abab”, p = “ab”
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 “ab”, 它是 “ab” 的异位词。
起始索引等于 1 的子串是 “ba”, 它是 “ab” 的异位词。
起始索引等于 2 的子串是 “ab”, 它是 “ab” 的异位词。

提示:

1 <= s.length, p.length <= 3 * 104
s 和 p 仅包含小写字母

求解

(1)遍历求解

var isAnagram = function(a, b) {const a1 = a.split('').sort();const b1 = b.split('').sort();return a1.join('') === b1.join('')
}
var findAnagrams = function(s, p) {if (s.length < p.length) return []let ans = []// 思路:遍历s,按照p的长度进行滑动进行判断for (let i = 0; i < s.length - p.length + 1; i++) {let item = s.slice(i, i + p.length)if (isAnagram(item, p)) {ans.push(i)}}return ans
};

暴力求解性能太差,超出时间限制了。学一学其他做法:
(2)滑动窗口
异位词的关键是:所含的字母的数量是一致的,一个大小为26的数组就可以将 所有字母包含:97-122(小写),所以定义一个数组,初始全为0,按照p的大小进行滑动,在判断数组是否一致就可以,我上面的方法有点类似,就是判断的方法有点太粗糙了。

代码如下:

var findAnagrams = function(s, p) {const s_l = s.length, p_l = p.lengthif (s_l < p_l) return []let ans = [] // 存储答案// 分别存储 p 个字母 出现的次数let s_count = new Array(26).fill(0)let p_count = new Array(26).fill(0)// 遍历p长度,初始化数组for (let i = 0; i < p_l; i++) {s_count[s.charCodeAt(i) - 97]++p_count[p.charCodeAt(i) - 97]++}// 判断第一个子串和p是否为异位词if (s_count.toString() === p_count.toString()) ans.push(0)// 判断其他子串for (let i = 0; i < s_l - p_l; i++) {// 去掉子串第一个字符s_count[s.charCodeAt(i) - 97]--// 加上下一个子串的最后一个字符s_count[s.charCodeAt(i + p_l) - 97]++// 判断是否为异位词if (s_count.toString() === p_count.toString()) ans.push(i + 1)}return ans
}

(3)继续优化

不再分别统计两个数组中包含字符的数量,而是 统计滑动窗口和字符串 p 中每种字母数量的差。定义两个变量:

  • count[26]: 0 表示和p 中对应的字符数量一致;1表示多一个,-1表示多一个
  • differ:统计字符数量不一致的 数量

判断的时候只需要判断 differ 是否为0即可。

var findAnagrams = function(s, p) {const s_l = s.length, p_l = p.lengthif (s_l < p_l) return []let ans = [] // 存储答案let count = new Array(26).fill(0)// 初始化数组,看for (let i = 0; i < p_l; i++) {count[s.charCodeAt(i) - 97]++count[p.charCodeAt(i) - 97]--}let differ = 0 // 表示的是和P不一致的个数// 初始化differfor (let i = 0; i < 26; i++) {if (count[i] !== 0) differ++}if (differ === 0) {ans.push(0)}// 滑动窗口,判断其他子串for (let i = 0; i < s_l - p_l; i++) {// 判断要移除的s[i]// 判断 要移除的 是不是原本就有的,所以减去之后就是0了。该字符就与p一致了if (count[s.charCodeAt(i) - 97] === 1) {differ-- // 与p不一致的少了一个} else if(count[s.charCodeAt(i) - 97] === 0) {// 要移除的,原本就没有,那么和p不一致的多了一个differ++}// 移除s[i]count[s.charCodeAt(i) - 97]--// 判断要加入的s[i + p_l]if (count[s.charCodeAt(i + p_l) - 97] === -1) {// 判断要加入的字符之前没有 → 说明和 p一致的多了一个differ--} else if (count[s.charCodeAt(i + p_l) - 97] === 0) {// 判断要加入的字符 已经存在了 → 说明 与p不一致的多了一个differ++}// 加入s[i + p_l]count[s.charCodeAt(i + p_l) - 97]++// 判断是否符合if (differ === 0) {ans.push(i + 1)}}return ans
};

补充

charCodeAt

charCodeAt 是 JavaScript 中 String 类型 的一个方法,它的作用是 返回字符串中指定索引位置的字符的 Unicode 编码。
语法:

str.charCodeAt(index)

index:必需,字符串中某个字符的索引(从 0 开始)。
返回值:指定字符的 Unicode 编码(一个 0-65535 之间的整数)。
举个栗子:

const str = "abc";console.log(str.charCodeAt(0)); // 输出 97 (字符 "a" 的 Unicode 编码)
console.log(str.charCodeAt(1)); // 输出 98 (字符 "b" 的 Unicode 编码)
console.log(str.charCodeAt(2)); // 输出 99 (字符 "c" 的 Unicode 编码)

常见用途

  • 字符比较:通过比较 Unicode 编码来判断字符的大小或顺序。

    const a = "a";
    const b = "b";console.log(a.charCodeAt(0) < b.charCodeAt(0)); // 输出 true
    
  • 字符转换:
    小写字母转大写字母:charCodeAt(0) - 32
    大写字母转小写字母:charCodeAt(0) + 32

    const lowerCase = "a";
    const upperCase = String.fromCharCode(lowerCase.charCodeAt(0) - 32);console.log(upperCase); // 输出 "A"
    
  • 判断字符类型:
    判断是否为大写字母:charCodeAt(0) >= 65 && charCodeAt(0) <= 90
    判断是否为小写字母:charCodeAt(0) >= 97 && charCodeAt(0) <= 122
    判断是否为数字:charCodeAt(0) >= 48 && charCodeAt(0) <= 57

    const char = "5";if (char.charCodeAt(0) >= 48 && char.charCodeAt(0) <= 57) {console.log("是数字");
    } else {console.log("不是数字");
    }
    
  • 注意:
    如果 index 超出了字符串的范围,charCodeAt 会返回 NaN。

    const str = "abc";
    console.log(str.charCodeAt(10)); // 输出 NaN
    

    charCodeAt 返回的是 Unicode 编码,而不是字符本身。如果想根据编码获取字符,可以使用 String.fromCharCode() 方法。

    console.log(String.fromCharCode(97)); // 输出 "a"
    
http://www.dtcms.com/a/614850.html

相关文章:

  • 土动静扭剪三轴仪技术指标
  • exe文件反编译成C语言 | 反编译技巧与应用分析
  • 指数型枚举
  • 竞价网站策划网站建设在作用是什么原因
  • 遵义住房城乡建设厅网站邯郸网站建设恋家
  • LeetCode 面试经典 150_二叉树_路径总和(75_112_C++_简单)(DFS)
  • 赋能职业教育:大众ID.4 CROZZ新能源汽车故障诊断仿真教学软件
  • 网站前端是什么意思品牌策划公司推荐
  • Linux字符设备驱动开发详细教程(简单字符设备驱动框架)
  • 电商网站建设运城商务网站建设难不难
  • 【Linux日新月异(三)】CentOS 7软件管理深度指南:从YUM到源码编译
  • 有了空间和域名 网站容易做吗长沙免费旅游景点大全
  • Linux网络NAT、代理服务和内网穿透
  • wordpress链接 颜色济南网站优化小黑
  • 微信授权登录第三方网站开发做h5网站的公司
  • 企业手机网站开通商城建站系统多少钱
  • 全栈项目实战经验,前后端分离开发流程
  • C# 中使用 Influxdb 1.x(四)——在程序内管理Influxdb服务的启停
  • 大模型的On-Policy Distillation(在线蒸馏策略)
  • 杭州网站建设公司有哪几家浅析社区网站的建设
  • ps手机网站页面设计网站主页设计模板
  • 常闭式4G远程开关,从硬件到软件整体实现
  • 找潍坊做网站的360网址大全电脑版
  • 怎么给网站做php后台库易网网站
  • 响应式网站模板xd公司网站管理规定
  • Linux命令-Emacs命令(纯文本网页浏览器)
  • 成都电商网站制作西安模板建站定制
  • aave v3 资产状态更新(updateState)合约代码解析
  • 淄博外贸网站建设公司wordpress首页调用文章多张图片
  • 自适应网站模板公司网站建设 趋势