【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

这篇具有很好参考价值的文章主要介绍了【剑指offer刷题记录 java版】数组双指针 之 滑动窗口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本系列文章记录labuladong的算法小抄中剑指offer题目



剑指 Offer 48. 最长不含重复字符的子字符串

题目链接:https://leetcode.cn/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> map = new HashMap();
        int left=0,right=0;
        int length=0;
        while(right<s.length()){
            char c = s.charAt(right);
            map.put(c,map.getOrDefault(c,0)+1);// 进行窗口内数据的一系列更新
            right++;
            while(map.get(c)>1){// 判断左侧窗口是否要收缩
                char temp = s.charAt(left);
                map.put(temp, map.get(temp)-1);
                left++;
            }
            length = Math.max(length,right-left);
        }
        return length;
    }
}

剑指 Offer II 014. 字符串中的变位词

题目链接:https://leetcode.cn/problems/MPnaiL/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        //map记录s1中包含的字母及数量
        Map<Character,Integer> map = new HashMap<>();
        for(int i=0;i<s1.length();i++){
            map.put(s1.charAt(i),map.getOrDefault(s1.charAt(i),0)+1);
        }

        //map2记录s2中,曾出现在s1中的字母及数量
        Map<Character,Integer> map2 = new HashMap<>();
        int left=0, right=0;
        int valid=0;//valid记录数量相同的字母的个数
        while(right<s2.length()){
            char c = s2.charAt(right);
            if(map.containsKey(c)){
                map2.put(c,map2.getOrDefault(c,0)+1);
                if (map2.get(c).equals(map.get(c)))
                    valid++;
            }
            right++;

            while(right-left==s1.length()){
                // 在这里判断是否找到了合法的子串
                if (valid == map.size())
                    return true;
                char d = s2.charAt(left);
                // 进行窗口内数据的一系列更新
                if (map.containsKey(d)) {
                    if (map2.get(d).equals(map.get(d)))
                        valid--;
                    map2.put(d, map2.get(d) - 1);
                }
                left++;
            }
        }
        return false;
    }
}

//因为只有26个小写英文字母,可以使用数组记录
class Solution {
    public boolean checkInclusion(String s1, String s2) {
        int n = s1.length(), m = s2.length();
        if (n > m) {
            return false;
        }
        int[] cnt = new int[26];
        for (int i = 0; i < n; ++i) {
            --cnt[s1.charAt(i) - 'a'];
            ++cnt[s2.charAt(i) - 'a'];
        }
        int diff = 0;
        for (int c : cnt) {
            if (c != 0) {
                ++diff;
            }
        }
        if (diff == 0) {
            return true;
        }
        for (int i = n; i < m; ++i) {
            int x = s2.charAt(i) - 'a', y = s2.charAt(i - n) - 'a';
            // 滑窗右边扩张左边收缩
            if (x == y) continue;
            if (cnt[x] == 0) {++diff;}
            ++cnt[x];
            if (cnt[y] == 0) {++diff;}
            --cnt[y];

            // 根据现状判断有几处不同
            if (cnt[x] == 0) {--diff;}
            if (cnt[y] == 0) {--diff;}
            if (diff == 0) {return true;}
        }
        return false;
    }
}

剑指 Offer II 015. 字符串中的所有变位词

题目链接:https://leetcode.cn/problems/VabMRr/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int m=s.length(), n=p.length();
        if(m<n){
            return new ArrayList<Integer>();
        }

        List<Integer> res = new ArrayList<>();
        int[] count = new int[26];
        for(int i=0;i<p.length();i++){
            count[p.charAt(i)-'a']--;
            count[s.charAt(i)-'a']++;
        }

        int diff=0;
        for(int num: count){
            if(num!=0) diff++;
        }
        

        if(diff==0){
            res.add(0);
        }

        for(int i=n; i<m;i++){
            //窗口下标范围为 [i-n, i)
            int index1 = s.charAt(i)-'a';//右边元素
            int index2 = s.charAt(i-n)-'a';//左边元素
            
            if(count[index1]==0) diff++;
            count[index1]++;
            if(count[index1]==0) diff--;

            if(count[index2]==0) diff++;
            count[index2]--;
            if(count[index2]==0) diff--;

            if(diff==0){
                res.add(i-n+1);
            }
        }
        return res;
    }
}

剑指 Offer II 016. 不含重复字符的最长子字符串

题目链接:https://leetcode.cn/problems/wtcaE1/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s=="")return 0;
        int left=0,right=0;
        int length=0;
        // 使用哈希表记录窗口内字符出现次数
        Map<Character, Integer> map = new HashMap<>();
        while(right<s.length()){
            char c = s.charAt(right);
            right++;
            map.put(c, map.getOrDefault(c,0)+1);

            //如果窗口中包含c
            while(map.get(c)>=2){
                char temp = s.charAt(left);
                map.put(temp, map.get(temp)-1);
                left++;
            }
            length=Math.max(length,right-left);
        }
        return length;
    }
}

剑指 Offer II 017. 含有所有字符的最短字符串(难)

题目链接:https://leetcode.cn/problems/M1oyTv/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?

class Solution {
    Map<Character, Integer> ori = new HashMap<Character, Integer>();
    Map<Character, Integer> cnt = new HashMap<Character, Integer>();

    public String minWindow(String s, String t) {
        int tLen = t.length();
        for (int i = 0; i < tLen; i++) {
            char c = t.charAt(i);
            ori.put(c, ori.getOrDefault(c, 0) + 1);
        }
        int l = 0, r = -1;
        int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;
        int sLen = s.length();
        while (r < sLen) {
            ++r;
            if (r < sLen && ori.containsKey(s.charAt(r))) {
                cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);
            }
            while (check() && l <= r) {
                if (r - l + 1 < len) {
                    len = r - l + 1;
                    ansL = l;
                    ansR = l + len;
                }
                if (ori.containsKey(s.charAt(l))) {
                    cnt.put(s.charAt(l), cnt.getOrDefault(s.charAt(l), 0) - 1);
                }
                ++l;
            }
        }
        return ansL == -1 ? "" : s.substring(ansL, ansR);
    }

    public boolean check() {
        Iterator iter = ori.entrySet().iterator(); 
        while (iter.hasNext()) { 
            Map.Entry entry = (Map.Entry) iter.next(); 
            Character key = (Character) entry.getKey(); 
            Integer val = (Integer) entry.getValue(); 
            if (cnt.getOrDefault(key, 0) < val) {
                return false;
            }
        } 
        return true;
    }
}

剑指 Offer 30. 包含min函数的栈

题目链接:https://leetcode.cn/problems/bao-han-minhan-shu-de-zhan-lcof/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

class MinStack {
    Deque<Integer> dq;
    Deque<Integer> minDq;

    /** initialize your data structure here. */
    public MinStack() {
        dq = new LinkedList<>();
        minDq = new LinkedList();
        minDq.offerLast(Integer.MAX_VALUE);//注意为了防止空栈,要在栈底添加最大元素
    }
    
    public void push(int x) {
        dq.offerLast(x);
        minDq.offerLast(Math.min(x,minDq.peekLast()));
    }
    
    public void pop() {
        dq.pollLast();
        minDq.pollLast();
    }
    
    public int top() {
        return dq.peekLast();
    }
    
    public int min() {
        return minDq.peekLast();
    }
}

剑指 Offer 59 - I. 滑动窗口的最大值(难)

题目链接:https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
【剑指offer刷题记录 java版】数组双指针 之 滑动窗口
单调队列

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        Deque<Integer> deque = new LinkedList<Integer>();
        for (int i = 0; i < k; ++i) {
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }

        int[] ans = new int[n - k + 1];
        ans[0] = nums[deque.peekFirst()];
        for (int i = k; i < n; ++i) {
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(i);
            while (deque.peekFirst() <= i - k) {
                deque.pollFirst();
            }
            ans[i - k + 1] = nums[deque.peekFirst()];
        }
        return ans;
    }
}

总结

滑动窗口要先扩张后收缩,即先移动右边指针,再移动左边指针。
固定大小的窗口使用for循环遍历,窗口大小不固定时使用while遍历。文章来源地址https://www.toymoban.com/news/detail-491305.html

到了这里,关于【剑指offer刷题记录 java版】数组双指针 之 滑动窗口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 刷题(双指针思想/滑动窗口思想/l螺旋矩阵)

    刚开始自己做就是无脑ac的,sort: 但是时间复杂度有问题, 是O(nlogn)的时间复杂度 提升:用双指针的思想:时间复杂度为O(n) 使用 双指针 的思想解决本题的思路: 以数组 为例: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 因为输入的数组是递增的,因此,平方后的最大值,只

    2023年04月08日
    浏览(38)
  • 【leetcode刷题之路】面试经典150题(2)——双指针+滑动窗口+矩阵

    2 双指针 2.1 【双指针】验证回文串 题目地址:https://leetcode.cn/problems/valid-palindrome/description/?envType=study-plan-v2envId=top-interview-150   详见代码。 2.2 【双指针】判断子序列 题目地址:https://leetcode.cn/problems/is-subsequence/description/?envType=study-plan-v2envId=top-interview-150   双指针挨个遍

    2024年02月19日
    浏览(34)
  • 【Leetcode刷题-Python/C++】长度最小的子数组(滑动窗口)

    209.长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数

    2023年04月08日
    浏览(27)
  • 刷题笔记【5】| 快速刷完67道剑指offer(Java版)

    本文已收录于专栏 🌻 《刷题笔记》 题目来源参考阿秀学长的刷题笔记,小戴只是把 C++的题解改成了 Java版本,并整理了其他思路,便于自己的学习~ 如果解题有更好的方法,本文也会及时进行更新~ 希望对你有帮助~ 一起加油哇~ 牛客原题链接 输入两个递增的链表,单个链表

    2023年04月12日
    浏览(22)
  • 《剑指offer》——刷题日记

    本期,给大家带来的是《剑指offer》几道题目的讲解。希望对大家有所帮助!!! 本文目录 (一)JZ36 二叉搜索树与双向链表 1、题意分析 2、思路讲解 3、代码演示 4、最终结果 (二)BM6 判断链表中是否有环 1、题意分析 2、思路讲解 3、代码演示 4、最终结果 (三)JZ23 链

    2023年04月21日
    浏览(26)
  • 剑指offer刷题笔记-链表

    少年何妨梦摘星 敢挽桑弓射玉衡 解决与链表相关的问题总是有大量的指针操作,而指针操作的代码总是容易出错的。很多面试官喜欢出与链表相关的问题,就是想通过指针操作来考察应聘者的编码功底。 题目链接 来自于 AcWing 、 Leetcode (LCR) 目录  从尾到头打印链表 题目

    2024年02月21日
    浏览(25)
  • 【leetcode刷题】剑指offer基础版(完结)

    剑指 Offer 05. 替换空格 剑指 Offer 58 - II. 左旋转字符串 剑指 Offer 67. 把字符串转换成整数❤️ 剑指 Offer 06. 从尾到头打印链表 剑指 Offer 24. 反转链表 剑指 Offer 35. 复杂链表的复制 剑指 Offer 18. 删除链表的节点 剑指 Offer 22. 链表中倒数第k个节点 剑指 Offer 25. 合并两个排序的链表

    2024年02月09日
    浏览(31)
  • 剑指offer刷题笔记--Num21-30

    目录 1--调整数组顺序使奇数位于偶数前面(21) 2--链表中倒数第 k 个节点(22) 3--反转链表(24) 4--合并两个排序的链表(25) 5--树的子结构(26) 6--二叉树的镜像(27) 7--对称的二叉树(28) 8--顺时针打印矩阵(29) 9--包含min函数的栈(30) 主要思路:         双指针

    2024年02月12日
    浏览(30)
  • 【leetcode刷题之路】剑指Offer(3)——搜索与回溯算法

    7 搜索与回溯算法 7.1 【BFS】剑指 Offer 32 - I - 从上到下打印二叉树 https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/   这里借助队列来实现广度优先遍历,由于需要访问每一层的节点,而且这一层访问才可以访问下一层,所以可以考虑队列的先进先出,先把每一层的节

    2024年02月13日
    浏览(40)
  • python_ACM模式《剑指offer刷题》链表1

    询问面试官是否可以改变链表结构 1. 翻转链表,再遍历链表打印。 2. 想要实现先遍历后输出,即先进后出,因此可借助栈结构。 3. 可用隐式的栈结构,递归来实现。 1. 2. 3. 采用递归的思想 注意是递归到最后一个元素才开始打印 即要先写递归 后写打印代码

    2024年01月23日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包