leetcode-hot100 子串

和为k的子数组

这个前缀和后的hashmap操作有点难想到

class Solution {
    public int subarraySum(int[] nums, int k) {
        int res = 0;

        int length = nums.length;
        int[] arr = new int[length+1];
        for(int i = 0;i < length;i++){
            arr[i+1] = nums[i]+arr[i];
        }
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for(int i = 0;i < arr.length;i++){
            int key = arr[i]-k;
            res += hashMap.getOrDefault(key,0);
            hashMap.put(arr[i],hashMap.getOrDefault(arr[i],0)+1);
        }
        return res;
    }
}

滑动窗口最大值

  1. 一个单调队列
  2. 每次遍历进行右加
  3. 每次遍历左边必须是不在窗口
  4. 当符合条件时,就要准备res了
  5. 记住,长为len的数组,右边下标为right,那么左边下标=right-len+1
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length < 2)return nums;
        //创建结果数组和单调队列,结果数组的大小还是非常简单判断的,带一个例子进去就行
        int length = nums.length;
        int[] res = new int[length-k+1];
        ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
        //对nums进行遍历
        for(int i = 0;i < length;i++){
            //往右边放是每次遍历都要放一个
            //但放入的前提是队列不为空且要把小的全拿走
            while (!arrayDeque.isEmpty() && nums[i] >= nums[arrayDeque.peekLast()]){
                arrayDeque.pollLast();
            }
            arrayDeque.offerLast(i);

            //弹出只有一个条件,即队首的不在窗口中(即小于了i-k),每遍历一次都进行判断
            if(arrayDeque.peekFirst() < i-k+1){
                arrayDeque.pollFirst();
            }
            //当窗口的下标满足了
            if(i-k+1 >= 0){
                res[i-k+1] = nums[arrayDeque.peekFirst()];
            }
        }
        return res;
    }
}

最小覆盖字串

class Solution {
    public String minWindow(String s, String t) {
        HashMap<Character,Integer> window = new HashMap<>();//用于记录当前窗口出现的字符及其数目
        HashMap<Character,Integer> need = new HashMap<>();//记录目标t中的字符及其数目
        //将t中字符放入need
        for(char c:t.toCharArray()){
            need.put(c,need.getOrDefault(c,0)+1);
        }
        int left = 0,right = 0;//左右指针[left,right)
        int valid = 0;//表示窗口中满足need条件(有效的valid)的字符个数
        int start = 0,len = Integer.MAX_VALUE;//start为结果字符的起始位置,len为字符串的长度
        while (right < s.length()){
            char c = s.charAt(right);
            right++;
            if(need.containsKey(c)){
                window.put(c,window.getOrDefault(c,0)+1);
                if(window.get(c).equals(need.get(c))){
                    valid++;
                }
            }


            while (valid == need.size()){
                //在满足条件的情况下,尝试收缩左边界,试图找到更小的len
                //只有当窗口的长度小于当前已知的最小长度时,才应该更新 start 和 len,但是只有start没有像min这样的函数呀
                if(right-left < len){
                    start = left;//
                    len = right-left;//相当于len = Math.min(len,right-left);
                }
                char d = s.charAt(left);
                left++;
                if(need.containsKey(d)){
                    if(window.get(d).equals(need.get(d))){
                        valid--;
                    }
                    window.put(d,window.get(d)-1);
                }
            }
        }
        return len==Integer.MAX_VALUE ? "":s.substring(start,start+len);
    }
}
   }
    }
    return len==Integer.MAX_VALUE ? "":s.substring(start,start+len);
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值