IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 滑动窗口 [搬运工、版权侵删] -> 正文阅读

[数据结构与算法]滑动窗口 [搬运工、版权侵删]

HashMap?

Java HashMap | 菜鸟教程

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。

HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。

HashMap 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。

基本类型对应的包装类表如下:

基本类型引用类型
booleanBoolean
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter

HashMap 类位于 java.util 包中,使用前需要引入它,语法格式如下:

import java.util.HashMap; // 引入 HashMap 类

以下实例我们创建一个 HashMap 对象 Sites, 整型(Integer)的 key 和字符串(String)类型的 value:

HashMap<Integer, String> Sites = new HashMap<Integer, String>();

//添加元素 添加键值对(key-value):
Sites.put(1, "Google");
Sites.put(2, "Runoob");
Sites.put(3, "Taobao");
Sites.put(4, "Zhihu");
//System.out.println(Sites);
//{four=Zhihu, one=Google, two=Runoob, three=Taobao}
        
//访问元素 获取 key 对应的 value:
Sites.get(3));
//System.out.println(Sites.get(3));
//Taobao

//删除元素 删除 key 对应的键值对(key-value):
Sites.remove(4);
//System.out.println(Sites);
//{1=Google, 2=Runoob, 3=Taobao}

//删除元素 删除所有键值对(key-value):
Sites.clear();
//System.out.println(Sites);
//{}

//计算大小 计算 HashMap 中的元素数量
Sites.size();
//System.out.println(Sites.size());
//4

containsKey()	//检查 hashMap 中是否存在指定的 key 对应的映射关系。
containsValue()	//检查 hashMap 中是否存在指定的 value 对应的映射关系。


3. 无重复字符的最长子串
滑动窗口

通常用来解决子串子序列子数组问题

什么是滑动窗口?

其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

时间复杂度:O(n)

1、首先,判断当前字符是否包含在map中,如果不包含,将该字符添加到map(字符,字符在数组下标),此时没有出现重复的字符,左指针不需要变化。此时不重复子串的长度为:i-left+1,与原来的maxLen比较,取最大值;

2、如果当前字符 ch 包含在 map中,此时有2类情况:
? ?1)当前字符包含在当前有效的子段中,如:abca,当我们遍历到第二个a,当前有效最长子段是 abc,我们又遍历到a,那么此时更新 left 为 map.get(a)+1=1,当前有效子段更新为 bca;
? ?2)当前字符不包含在当前最长有效子段中,如:abba,我们先添加a,b进map,此时left=0,我们再添加b,发现map中包含b, 而且b包含在最长有效子段中,就是1)的情况,我们更新 left=map.get(b)+1=2,此时子段更新为 b,而且map中仍然包含a,map.get(a)=0;
随后,我们遍历到a,发现a包含在map中,且map.get(a)=0,如果我们像1)一样处理,就会发现 left=map.get(a)+1=1,实际上,left此时应该不变,left始终为2,子段变成 ba才对。

为了处理以上2类情况,我们每次更新left,left=Math.max(left , map.get(ch)+1).
另外,更新left后,不管原来的 s.charAt(i) 是否在最长子段中,我们都要将 s.charAt(i) 的位置更新为当前的i,
因此此时新的 s.charAt(i) 已经进入到 当前最长的子段中!

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s.length() == 0) 
            return 0;

        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        int maxLen = 0; //无重复子串的 最长字串的 长度
        int left = 0; //滑动窗口左指针

        for(int i = 0; i < s.length(); i++){
            if(map.containsKey(s.charAt(i))){ //判断当前字符是否包含在map中
                left = Math.max(left,map.get(s.charAt(i)) + 1);
            }  //charAt()方法用于返回指定索引处的字符
               //索引范围为从 0 到 length() - 1  String类
            map.put(s.charAt(i),i);
            maxLen = Math.max(maxLen,i-left+1);
        }
        return max;
        
    }
}

作者:powcai
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Java List接口

Java List<>的用法及其方法_Pompey_hpy的博客-CSDN博客_java list<>

Java 集合框架 | 菜鸟教程

List包括List接口以及List接口的所有实现类。因为List接口实现了Collection接口,所以List接口拥有Collection接口提供的所有常用方法,又因为List是列表类型,所以List接口还提供了一些适合于自身的常用方法。

在这里插入图片描述

List接口提供的适合于自身的常用方法均与索引有关,这是因为List集合为列表类型,以线性方式存储对象,可以通过对象的索引操作对象。
List接口的常用实现类有ArrayListLinkedList,在使用List集合时,通常情况下声明为List类型,实例化时根据实际情况的需要,实例化为ArrayList或LinkedList,例如:

List<String> l = new ArrayList<String>();// 利用ArrayList类实例化List集合
List<String> l2 = new LinkedList<String>();// 利用LinkedList类实例化List集合

Java ArrayList | 菜鸟教程

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。?

ArrayList 继承了 AbstractList ,并实现了 List 接口。

ArrayList 类位于 java.util 包中,使用前需要引入它,语法格式如下:

import java.util.ArrayList; // 引入 ArrayList 类

ArrayList<E> objectName =new ArrayList<>();  // 初始化

?30. 串联所有单词的子串

1. 总共用到两个哈希表,allWords 用于记录 words 中单词出现的次数,hasWords 用于记录子串中(也就是滑动窗口中)单词出现的次数
2. wordNum 为单词的个数,wordLen 为单词长度
3. 遍历字符串,移动长度为 wordNum * wordLen 的滑动窗口,再在当前滑动窗口中依次比较wordLen长度的单词
4. 当这个窗口内一旦出现不存在 allWords 中的单词,或者这个单词在子串中出现的次数已经等于 allWords 中的次数(也就是再加入这个子串次数就要超出了),这个滑动窗口就不符合要求,直接 break 进入下一个滑动窗口的匹配
5. 一旦完全匹配上了,把滑动窗口的起始索引加入结果 res 中

  • 时间复杂度:O(n*m)n为字符串长度,m为单词个数
  • 空间复杂度:O(m)

作者:edelweisskoko
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/solution/30-chuan-lian-suo-you-dan-ci-de-zi-chuan-bvy9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        //allWords存储words中的所有单词
        HashMap<String, Integer> allWords = new HashMap<String, Integer>();
        for(String word : words){//for (Object o : list) { System.out.println(o);}
                            //优点:简洁结合泛型使用更简洁
                            //缺点:jdk1.4向下不兼容
                            //for (int i = 0; i < list.size(); i++) 
                            //{ System.out.println(list.get(i));}
            //getOrDefault获取 word 所对应的value; 没有 word, 返回默认值 0 
            allWords.put(word, allWords.getOrDefault(word,0) + 1); //将 word 存储进 map
        }

        List<Integer> res = new ArrayList<Integer>();
        int wordNum = words.length; //words里面有几个单词
        int wordLen = words[0].length(); //每个单词的长度, 题目隐藏条件:每个单词长度相等
        if(wordNum == 0)
            return res;

        for (int i = 0; i < s.length() - wordNum * wordLen + 1; i++){
            //hasWord存储s的子串中的单词
            HashMap<String, Integer> hasWords = new HashMap<String, Integer>();
            int index = i;

            while(index < i + wordNum * wordLen){
                String curWord = s.substring(index, index + wordLen);
                //判断word是否在map中
                if(!allWords.containsKey(curWord) || hasWords.get(curWord) == allWords.get(curWord)){//get()	获取指定 key 对应对 value
                    break;   
                }
                hasWords.put(curWord, hasWords.getOrDefault(curWord,0) + 1);
                index += wordLen;
            }
            if (index == i + wordNum * wordLen)
                res.add(i); 
        }

    return res;    
    }   
}

76. 最小覆盖子串

我写了一首诗,把所有滑动窗口问题变成了默写题

//模板
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> window = new HashMap<>();

    for (char c : t.toCharArray()) 
        need.put(c, need.getOrDefault(c,0) + 1);
     int left = 0, right = 0; //双指针 左开右闭区间[left, right)为一个窗口
     int valid = 0; // 窗口中满足need条件的字符个数

     while (right < s.size()) {
         // c 是将移入窗口的字符
         char c = s.charAt(right);
         // 右移窗口
         right ++;
         // 进行窗口内数据的一系列更新 
         // 目的在于寻找一个【可行解】
         ...

         /*** debug 输出的位置 ***/
         System.out.println("window: ["+left+","+ right+")");
         /********************/
    
         // 判断左侧窗口是否要收缩
         while (window needs shrink) {
             // d 是将移出窗口的字符
             char d = s[left];
             // 左移窗口
             left ++;
             // 进行窗口内数据的一系列更新
             ...
            // 目的在于优化【可行解】,最终找到【最优解】
         }
     }
}
class Solution {
    public String minWindow(String s, String t) {
        //need中存储的时需要的字符以及需要的字符所对应的数量
        HashMap<Character, Integer> need = new HashMap<Character, Integer>();
        for(char c : t.toCharArray()){ //toCharArray() 方法将字符串转换为字符数组
            need.put(c, need.getOrDefault(c,0)+1);
        }

        HashMap<Character, Integer> window = new HashMap<Character, Integer>();
        int left = 0, right = 0; //双指针
        int count = 0; //记录当前窗口中符合need要求的字符的数量,当count==need.size()时即可shrink窗口
        int start = 0; //符合最优解的substring的起始索引
        int len = Integer.MAX_VALUE; //记录最终窗口的长度,以len作比较,淘汰选出最小的substring的len
        while(right < s.length()){
            //更新窗口
            char c = s.charAt(right);
            right ++; //窗口扩大
            if(need.containsKey(c)){
                window.put(c, window.getOrDefault(c,0)+1);
                if(need.get(c).equals(window.get(c))){
                    count++;
                }
            }
            //判断左侧窗口是否要收缩
            while(count == need.size()){
                //更新最小覆盖子串
                if(right - left < len){
                    len = right - left;
                    start = left;
                }

                char d = s.charAt(left); //d是将移除窗口的字符
                left ++; //窗口缩小,左移窗口
                //进行窗口数据的一系列更新
                if(need.containsKey(d)){   
                    if(need.get(d).equals(window.get(d))){
                        count--;
                    }
                    window.put(d, window.getOrDefault(d,0)-1);
                } 
            }
            

        }
        //返回最小覆盖子串
        return len == Integer.MAX_VALUE ? "":s.substring(start, start+len);   //int y = x1 == null ? 0 : x; 
                                                                            // if(x1==null){
                                                                            // 	y = 0;
                                                                            // }else{
                                                                            // 	y = x;
                                                                            // }

    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-14 01:32:52  更:2022-04-14 01:45:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:37:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码