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

制作网站模板教程app推广策略

制作网站模板教程,app推广策略,深圳汽车网站建设,深圳营销型网站开发这是滑动窗口的另一道题目,难度为中等。 让我们来看看题目描述: 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s “cbaebabacd”, p “abc” 输出: …

这是滑动窗口的另一道题目,难度为中等。
让我们来看看题目描述:

给定两个字符串 sp,找到 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 * 1 0 4 10^4 104
  • sp 仅包含小写字母

说人话环节:

给定两个字符串 s 和 p,找到 s 中所有与 p 字符组成相同(顺序不限)的子串,并返回这些子串的起始位置。

题解

class Solution {public List<Integer> findAnagrams(String s, String p) {// 创建一个哈希表,用来存储 p 中每个字符及其需要的出现次数Map<Character, Integer> need = new HashMap<>();// 创建一个哈希表,用来存储当前滑动窗口中各字符的出现次数Map<Character, Integer> window = new HashMap<>();// 遍历 p 中的每个字符,将每个字符的出现次数记录到 need 中for(char c : p.toCharArray()){need.put(c, need.getOrDefault(c, 0) + 1);}// 初始化左右指针,表示滑动窗口的左右边界int left = 0, right = 0;// valid 用来记录窗口中满足 need 条件的字符种数int valid = 0;// 用于存储所有找到的异位词子串的起始索引List<Integer> res = new ArrayList<>();// 开始滑动窗口遍历 s 字符串while(right < s.length()){// 取出当前右边界的字符,并将右指针右移一位char c = s.charAt(right);right++;// 如果当前字符是 p 中需要的字符if(need.containsKey(c)){// 更新窗口中该字符的数量window.put(c, window.getOrDefault(c, 0) + 1);// 如果当前窗口中该字符的数量与 need 中要求的数量相等,valid 加 1if(window.get(c).equals(need.get(c))){valid++;}}// 当窗口大小达到 p 的长度时,开始判断和调整窗口while(right - left >= p.length()){// 如果 valid 等于 need 中键的数量,说明当前窗口中的字符完全满足 p 的要求,是 p 的一个异位词if(valid == need.size()){res.add(left); // 将当前窗口的起始索引加入结果列表}// 准备移除窗口左边界的字符char d = s.charAt(left);left++;// 如果移除的字符是 p 中需要的字符,则更新窗口数据if(need.containsKey(d)){// 如果窗口中该字符的数量正好符合要求,则 valid 需要减 1if(window.get(d).equals(need.get(d))){valid--;}// 窗口中该字符的数量减 1window.put(d, window.get(d)-1);}}}// 返回所有找到的异位词子串的起始索引return res;}
}

我们来回忆一下滑动窗口基本模板:

int left = 0, right = 0;while (right < nums.size()) {// 增大窗口window.addLast(nums[right]);right++;while (window needs shrink) {// 缩小窗口window.removeFirst(nums[left]);left++;}
}

实例

我们以以下实例来大致模拟一下整个过程:

输入:
s = “cbaebabacd”
p = “abc”
输出: [0,6]

整体思路是使用固定大小为 p.length() 的滑动窗口来检测窗口内的字符是否能构成 p 的异位词。当窗口大小达到 p 的长度后,我们需要把窗口最左边的字符移除,为下一次比较腾出位置。

下面是这段代码在窗口缩小时的具体过程:

假设前面已经完成了以下初始化工作:

  • need = {‘a’:1, ‘b’:1, ‘c’:1}(记录 p 中每个字符出现的次数)
  • window:当前窗口中各字符的统计(初始为空)
  • left = 0, right = 当前右指针位置,valid 表示窗口中满足 need 条件的字符种数
  • 当窗口的大小 right - left 等于 p 的长度(即3)时,我们检查 valid 是否等于 need 的大小(3),如果相等就说明窗口中字符完全匹配 p(构成异位词),记录当前 left;随后需要通过调整窗口来继续检测后续位置。

接下来重点看缩小窗口这一段代码(当窗口长度固定为 p 的长度时):

char d = s.charAt(left);
left++;if(need.containsKey(d)){if(window.get(d).equals(need.get(d))){valid--;}window.put(d, window.get(d)-1);
}

我们结合具体的运行过程说明:

1. 初始阶段形成第一个窗口

  • 索引 0 到 2:
    读取字符:
    • s[0] = ‘c’ → 更新 window:{‘c’:1},由于 window[‘c’] 与 need[‘c’] 匹配,valid 从 0 增加到 1。
    • s[1] = ‘b’ → 更新 window:{‘c’:1, ‘b’:1},window[‘b’] 与 need[‘b’] 匹配,valid 增加到 2。
    • s[2] = ‘a’ → 更新 window:{‘c’:1, ‘b’:1, ‘a’:1},window[‘a’] 与 need[‘a’] 匹配,valid 增加到 3。
      此时窗口大小为 3(即 p 的长度),并且 valid 等于 3(need 中不同字符个数),说明从索引 0 开始的子串 “cba” 是一个异位词,因此记录索引 0到结果中。

2. 开始缩小窗口,准备移动窗口

当窗口大小固定为 3 时,需要调整窗口:

  • 移除索引 0 的字符 ‘c’:
    • 执行 char d = s.charAt(left); 取出 ‘c’,然后 left++ 将 left 从 0 变为 1。
    • 检查 if(need.containsKey(d)):‘c’ 在 need 中,所以继续检查。
    • 判断 if(window.get(d).equals(need.get(d))):此时 window[‘c’] 是 1,与 need[‘c’] 也为 1,说明 ‘c’ 正好满足条件,所以 valid 减 1,从 3 变为 2。
    • 然后执行 window.put(d, window.get(d)-1);,将 window[‘c’] 从 1 减为 0。
      此操作完成后,当前窗口变为索引 [1,2](对应字符 “ba”),valid = 2。

这段代码的意义就在于:

  • 将窗口左侧最旧的字符移出窗口
  • 如果移出的字符正好满足 need 的要求(即移除前窗口中该字符的数量刚好符合需要),那么 valid 计数也要减少,因为窗口现在少了一个完全匹配的字符
  • 同时更新 window 中该字符的数量

3. 窗口继续滑动

接下来程序继续将右指针右移,补充窗口字符,再次达到窗口大小为 3后再做判断和移除:

  • 举例说明后续部分(关键节点):
    • 当 right 指针移动并形成新的窗口 “bac” 时(对应索引 6 到 8),窗口中的统计变为 {‘b’:1, ‘a’:1, ‘c’:1},此时 valid 恢复到 3(因为相应字符数量与 need 完全匹配),因此记录索引 6。
    • 紧接着,为了继续滑动窗口,又会执行一次缩小操作:移除当前窗口最左边的字符(如索引 6 的字符 ‘b’),如果移除前 window[‘b’] 恰好等于 need[‘b’](1),那么 valid 就会减少,保证窗口统计更新正确。

这一段代码的作用就是在每次窗口达到固定长度 p.length() 后,通过移除窗口最左边的字符来“滑动”窗口,并同步更新窗口中每个字符的计数以及 valid 指标,从而为后续比较做准备。如果不移除最左边的字符,窗口就会一直增大,就无法保持与 p 长度一致的窗口去判断是否为异位词。

通过不断移动右指针加入新字符,并用这段代码移除旧字符,我们就能遍历整个字符串 s,找出所有符合条件的异位词子串。最终在本例中,我们得到的结果是 [0,6],分别对应 “cba”(索引 0)和 “bac”(索引 6)。

问题与解答

[NOTE] 问题1
window这个hashmap中其实也只会有a、b、c三个key吗?其他的字符只会存在于left到right这个双指针之中对吗?
解答:
是的,window 这个 HashMap 只会存储 p 中出现的字符(在本例中是 ‘a’、‘b’ 和 ‘c’),因为只有当当前字符在 need 中(即在 p 中)时才会将其加入或更新 window。对于 s 中其他不在 p 中的字符,虽然它们依然会被 right 指针经过,但不会加入到 window 中,只在滑动窗口内存在,而不记录在 window 这个映射中。

[NOTE] 问题2
我是否可以这样理解:
window和need这两个hashmap的key其实是一样的,不一样的是value的值,作为要找出的子串hashmap,need中保存每个字符出现的次数,而window的作用只是拿来与need进行对比,在滑动窗口的移动过程中,window中每个key的字符出现次数会改变,所以设置一个valid。
valid++的条件是if (window.get(c).equals(need.get(c))),只有当window和need中的valid == need.size()条件满足时,才会记录左指针left的值存入res。这才是这个算法最重要的判断条件对吗?
解答:
你的理解是正确的。简要总结如下:

  • 相同的 Key 集合
    needwindow 的 key 集合是一样的,都是 p 中出现的字符。

  • value 的含义不同

    • need 保存的是 p 中每个字符需要的出现次数。
    • window 动态记录当前滑动窗口中这些字符的实际出现次数。
  • valid 的作用
    window 中某个字符的出现次数达到 need 中的要求时,就会对 valid 进行累加。只有当 valid 的值等于 need.size() 时,说明当前窗口中的字符种类和数量都满足 p 的要求,此时可以认为这个窗口内的子串是 p 的一个异位词,因此记录下 left 的位置。

这正是该算法的核心判断条件。

完整程序可调试

以下是可在编译器调试的完整代码,需要自取:

import java.util.*;public class test_438 {public static void main(String[] args) {// 输入样例String s = "cbaebabacd";String p = "abc";// 创建 Solution 对象并调用 findAnagrams 方法Solution solution = new Solution();List<Integer> result = solution.findAnagrams(s, p);// 输出结果System.out.println("输出: " + result);}
}class Solution {public List<Integer> findAnagrams(String s, String p) {// 创建 need 哈希表,用于存储 p 中每个字符及其需要的出现次数Map<Character, Integer> need = new HashMap<>();// 创建 window 哈希表,用于存储当前滑动窗口中各字符的出现次数Map<Character, Integer> window = new HashMap<>();// 统计 p 中每个字符出现的次数for (char c : p.toCharArray()) {need.put(c, need.getOrDefault(c, 0) + 1);}int left = 0, right = 0;// valid 用于记录窗口中满足 need 条件的字符种数int valid = 0;// 用于存储所有找到的异位词子串的起始索引List<Integer> res = new ArrayList<>();// 开始滑动窗口遍历 s 字符串while (right < s.length()) {// 当前加入窗口的字符char c = s.charAt(right);right++;// 如果当前字符是 p 中需要的字符,则更新窗口数据if (need.containsKey(c)) {window.put(c, window.getOrDefault(c, 0) + 1);if (window.get(c).equals(need.get(c))) {valid++;}}// 当窗口大小达到 p 的长度时,检查并缩小窗口while (right - left >= p.length()) {// 如果 valid 等于 need 中字符的种数,则说明当前窗口为异位词if (valid == need.size()) {res.add(left);}// 移除窗口最左边的字符,准备缩小窗口char d = s.charAt(left);left++;// 如果移除的字符是 p 中需要的字符,更新窗口数据if (need.containsKey(d)) {if (window.get(d).equals(need.get(d))) {valid--;}window.put(d, window.get(d) - 1);}}}return res;}
}
http://www.dtcms.com/wzjs/386751.html

相关文章:

  • 建设网站培训百度关键词指数查询
  • 外贸网站定做营销策略的重要性
  • 遵义网站建设深圳关键词优化怎么样
  • 珠海网站seoseo线上培训多少钱
  • 在哪下载免费的英文版网站模板网站关键词优化价格
  • 网站优化公司哪家效果好个人网页设计作品欣赏
  • 做外贸的专业网站项目推广网站
  • 汽车之家网站是谁做的网站设计公司多少钱
  • 鼠标滚轮翻页网站模板百度手机
  • 5118网站的功能找人帮忙注册app推广
  • 南昌市做网站热门seo推广排名稳定
  • 个人免费网站怎么建设搜索引擎优化技术都有哪些
  • 免费开源网站系统百度极速版
  • 阿里云网站建设有什么好处免费建站网站一站式
  • 重庆阳光政务投诉热线seo关键词排名注册价格
  • 汕头拿家做网站制作网站的网址
  • 个人网站需要公安备案吗湖北百度推广公司
  • 商城网站开发合同农产品营销方案
  • 黄岛网站建设哪家专业学生网页设计模板
  • 求个网站好人有好报2023信阳网站推广公司
  • 怎么注册一个网站百度营销登录
  • 大港手机网站建设网络广告策划方案
  • 武汉市住房和城乡建设局网站自创网站
  • 做网站还有用百度动态排名软件
  • 海口建站程序seo网站优化服务商
  • 网站域名怎么看百度推广优化
  • 在线p图优化网站标题和描述的方法
  • 装饰行业做网站seo外包方案
  • wordpress前端登陆关键词优化一般收费价格
  • 网站后台怎么做水印图片宁德市医院