标签8滑动窗口与岛屿问题

tech2023-09-19  103

标签8滑动窗口与岛屿问题

 

滑动窗口

 

[left,right]左闭右闭区间表示一个滑动窗口。

1.初始化为left,right都是“小的”,保证left和right都是向右滑动,也就是得left ++,right ++。

2.其次就是判断什么时候left  ++,什么时候right ++。

3.终止条件一般是right小于一个阈值,但是有的问题left 小于一个阈值也是可以的。

4.字符串类的滑动窗口的题目中map可以使用int[256]数组来代替,java里char是一个字节,8位。可以把空间复杂度降低为O(1)

int[X] = 1;代表阿西克码是X的字符对应最近出现的下标,类似于HashMap的key和value(这里的value也是用来记录最近出现的下标)

3. 无重复字符的最长子串

class Solution { public int lengthOfLongestSubstring(String s) { if(s.length() <= 1) { return s.length(); }else { int left = 0; int right = 0; int maxlength = 1; //map.put(s.charAt(right),right); HashMap<Character,Integer> map = new HashMap<>(); while(right < s.length()) { //下面两个while可以改成if while( right < s.length() && (! map.containsKey(s.charAt(right)) || map.get(s.charAt(right)) < left)) { maxlength = Math.max(maxlength,right - left + 1); map.put(s.charAt(right),right); right ++; } while(right < s.length() && map.containsKey(s.charAt(right)) && map.get(s.charAt(right)) >= left) { /* left = right; right = left; */ //left ++; left = Math.max(left + 1,map.get(s.charAt(right))); //right = left; } } return maxlength; } } }

 解法:上面的改进

class Solution { public int lengthOfLongestSubstring(String s) { if(s.length() <= 1) { return s.length(); }else { int left = 0; int right = 0; int maxlength = 1; char tem; //模拟一下先放进去肯定不对 //map.put(s.charAt(right),right); //map存储的是字符靠近right出现的位置 HashMap<Character,Integer> map = new HashMap<>(); while(right < s.length()) { tem = s.charAt(right); //map中含有tem关键字,可能这个关键字的下标小于left //就是和s.charAt(right)重复的不在滑动窗口之内,不用理睬 if(map.containsKey(tem)) { left = Math.max(left,map.get(tem) + 1); } //直接put即可,不用关心tem这个关键字是否已经存在,即使存在也要覆盖 map.put(tem,right); maxlength = Math.max(maxlength,right - left + 1); right ++; } return maxlength; } } }

解法:HashMap的改进,空间复杂度降为O(1) ,用int[256]来代替hashmap,作用一样,初始化int数组为-1,不能是0

class Solution { public int lengthOfLongestSubstring(String s) { if(s.length() <= 1) { return s.length(); }else { int left = 0; int right = 0; int maxlength = 1; char tem; //int数组是用来代替map的 int[] indexes = new int[256]; //数组的初始值应该是-1,表示初始的时候,阿西克码对应的下标不存在 //初始化化为0,代表indexes[X],阿西克码为X的下标是0,显然不对 for(int i = 0;i < 256;i ++) { indexes[i] = -1; } while(right < s.length()) { tem = s.charAt(right); //map中含有tem关键字,可能这个关键字的下标小于left //就是和s.charAt(right)重复的不在滑动窗口之内,不用理睬 //之前判断是indexes[tem] == 0这是不对的,因为之前把indexes数组的值初始化为0, if(indexes[tem] != -1) { left = Math.max(left,indexes[tem] + 1); } indexes[tem] = right; maxlength = Math.max(maxlength,right - left + 1); right ++; } return maxlength; } } }

剑指 Offer 57 - II. 和为s的连续正数序列

解法:滑动窗口,终止条件是left < (target + 1) / 2,因为再大就没有意义了;其次找到等于target的组合,right或者left要增加,否则死循环。

class Solution { public int[][] findContinuousSequence(int target) { List<int[]> answer = new ArrayList<>(); if(target <= 0) { return null; }else { int left = 1; int right = 2; int currentsum = left + right; //当small大于stopflag的时候,区间[left,right]的和肯定大于target int stopflag = (target + 1) / 2; while(left < stopflag) { if(currentsum == target) { //每个list都得新new int[] array = new int[right - left + 1]; for(int i = left;i <= right;i ++) { array[i - left] = i; } answer.add(array); //相等的时候,一定要移动left或者right,要不然程序一直循环 //移动left,right都可以 /* right ++; currentsum += right; */ currentsum -= left; left ++; } //下面两个的while改成else if也可以,不过while更快 while(currentsum < target) { right ++; currentsum += right; } while(currentsum > target && left < stopflag) { //这个得先减去 currentsum -= left; left ++; } } return answer.toArray(new int[answer.size()][]); } } }

岛屿问题

https://leetcode-cn.com/problems/number-of-islands/solution/dao-yu-lei-wen-ti-de-tong-yong-jie-fa-dfs-bian-li-/

待完成

最新回复(0)