【算法】滑动窗口三步走 (9)

【算法】滑动窗口三步走

我的:
答案一:使用map,超时

class Solution { public List<Integer> findAnagrams(String s, String p) { // 固定窗口大小为p.length() - 1 int left = 0; int right = p.length(); List<Integer> list = new ArrayList<>(); Map<Character, Integer> mapP = new HashMap<>(); Map<Character, Integer> mapS = new HashMap<>(); // 将p的所有字符放入哈希表 for (int i = 0; i < p.length(); i++) { char c = p.charAt(i); int count = mapP.getOrDefault(c, 0) + 1; mapP.put(c, count); } while (right <= s.length()) { // 从left到right,遍历窗口 for (int i = left; i < right; i++) { char c = s.charAt(i); int count = mapS.getOrDefault(c, 0) + 1; mapS.put(c, count); } if (mapP.equals(mapS)) { list.add(left); } // 无论如何都要前进 left++; right++; // 清理一下mapS,便于下个窗口存入 mapS.clear(); } return list; } }

答案二:上面的算法面对超长超大的字符串会超时,所以我们把哈希表换成了自己写的

// 上面的算法面对超长超大的字符串会超时,所以我们把哈希表换成了自己写的 class Solution { public List<Integer> findAnagrams(String s, String p) { int left = 0; int right = p.length(); int[] mapP = new int[26]; // p的哈希表 int[] mapS = new int[26]; // s的哈希表 List<Integer> list = new ArrayList<>(); // 将p的所有字符放入哈希表 for (int i = 0; i < p.length(); i++) { mapP[p.charAt(i) - 'a']++; } // 由于前闭后开,所以right得等于s.length()才算遍历完了所有 while (right <= s.length()) { mapS = new int[26]; for (int i = left; i < right; i++) { mapS[s.charAt(i) - 'a']++; } if (isSame(mapP, mapS)) { list.add(left); } left++; right++; } return list; } public boolean isSame(int[] mapP, int[] mapS) { for (int i = 0; i < mapP.length; i++) { if (mapP[i] != mapS[i]) { return false; } } return true; } } 239. 滑动窗口最大值(困难可不做)

第239题:给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值所构成的数组。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]

解释:

滑动窗口的位置 最大值

[1 3 -1] -3 5 3 6 7 3

1 [3 -1 -3] 5 3 6 7 3

1 3 [-1 -3 5] 3 6 7 5

1 3 -1 [-3 5 3] 6 7 5

1 3 -1 -3 [5 3 6] 7 6

1 3 -1 -3 5 [3 6 7] 7

题目分析

本题对于题目没有太多需要额外说明的,应该都能理解,直接进行分析。我们很容易想到,可以通过遍历所有的滑动窗口,找到每一个窗口的最大值,来进行暴力求解。那一共有多少个滑动窗口呢,小学题目,可以得到共有 L-k+1 个窗口。

假设 nums = [1,3,-1,-3,5,3,6,7],和 k = 3,窗口数为6

【算法】滑动窗口三步走

根据分析,直接完成代码:

//java class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int len = nums.length; if (len * k == 0) return new int[0]; int [] win = new int[len - k + 1]; //遍历所有的滑动窗口 for (int i = 0; i < len - k + 1; i++) { int max = Integer.MIN_VALUE; //找到每一个滑动窗口的最大值 for(int j = i; j < i + k; j++) { max = Math.max(max, nums[j]); } win[i] = max; } return win; } }

【算法】滑动窗口三步走


It's Bullshit!结果令我们很不满意,时间复杂度达到了O(LK),如果面试问到这道题,基本上只写出这样的代码,一定就挂掉了。那我们怎么样优化时间复杂度呢?有没有可以O(L)的实现呢?=_=

线性题解

这里不卖关子,其实这道题比较经典,我们可以采用队列,DP,堆等方式进行求解,所有思路的主要源头应该都是在窗口滑动的过程中,如何更快的完成查找最大值的过程。但是最典型的解法还是使用双端队列。具体怎么来求解,一起看一下。

首先,我们了解一下,什么是双端队列:是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出或者插入。

【算法】滑动窗口三步走

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwyxf.html