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

标签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-/

待完成

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值