Skip to content

Latest commit

 

History

History
329 lines (310 loc) · 9.88 KB

滑动窗口.md

File metadata and controls

329 lines (310 loc) · 9.88 KB

数组的滑动全窗口

 public int sumInSubArrays(int[] ints) {
        if (ints == null || ints.length == 0) {
            return 0;
        }
        return dfs(ints, 0);
    }

    public int dfs(int[] arrs, int n) {
        int s = (n << 1) + 1;
        int sum = 0;
        if (s > arrs.length) {
            return 0;
        }
        for (int i = 0; i < s; i++) {
            sum += arrs[i];
        }

        int tmpSum = sum;
        for (int i = s; i < arrs.length; i++) {
            tmpSum += arrs[i] - arrs[i-s];
            sum += tmpSum;
        }

        return sum + dfs(arrs, s);
    }

重复元素的原地删除

过程的表述 想实现这过程,有:
1,fast指针在和前面的元素不等的时候呢,我就加到nums[slow++]中去。

滑动窗口的2类

1,有k个的限制了。

for(int i = 0; i < n; i++) {
	if(i > k) {
		set.remove(nums[i-k]);
	}
}

2,对数据的连续字符串
可以对if(i > 0) {set.remove(nums[i])}

判断2个字符串中一个是另一个的子串

/**
     * 需要2个条件:1,个数;2,种类要相等。
     * @param s1
     * @param s2
     * @return
     */
    public boolean checkInclusion(String s1, String s2){
        char[] pattern = s1.toCharArray();
        char[] text = s2.toCharArray();

        int pLen = s1.length();
        int tLen = s2.length();

        int[] preF = new int[26];
        int[] wFre = new int[26];
        for (int i = 0; i < pLen; i++) {
            preF[pattern[i]-'a']++;
        }
        int pCnt = 0;
        for (int i = 0; i < pLen; i++) {
            if (preF[i] > 0) {
                pCnt++;
            }
        }
        int left = 0, right = 0;
//        滑动窗口的字、符与s1对应相等的时候。
        int winCnt = 0;
        while(right < tLen) {
            if(preF[text[right]-'a'] > 0) {
                wFre[text[right]-'a']++;
                if (wFre[text[right]-'a'] == preF[text[right]-'a']){
                    winCnt++;
                }
            }
            right++;
            while (pCnt == winCnt){
                if (right- left == pLen){
                    return true;
                }
                if (preF[text[left]-'a'] > 0) {
                    wFre[text[left]-'a']--;
                    if (wFre[text[left]-'a'] < preF[text[left]-'a']) {
                        winCnt--;
                    }
                }
                left++;
            }
        }
        return false;
    }

重复元素不超过2个

原题连接

public int removeDuplicate(int[] nums) {
    int n = nums.length;
	if(n < 2) {
		return 2;
	}
	int slow = 2,fast = 2;
	while(fast < n) {
		if(nums[slow-2] != nums[fast]){
			nums[slow] = nums[fast];
			slow++;
		}
		++fast;
	} 
	return slow;
}
//原地修改数组,使得所有的元素只出现一次,因为是要的长度啊。
public int removeOne(int[] nums) {
	 if (nums.length == 0) return 0;
    int i = 0;
    for (int j = 1; j < nums.length; j++) {
        if (nums[j] != nums[i]) {
            i++;
            nums[i] = nums[j];
        }
    }
    return i + 1;
}

滑动窗口的最大差值不能超过target

原题目链接

//滑动窗口的题目了。有什么要注意的是什么?
public int limit(int[] nums, int limit) {
    TreeMap<Integer> map = new TreeMap();
    int n = nums.length;
    int left = 0, right = 0;
    int ret = 0;
    while(right < n) {
        map.put(nums[right], map.getOrDefalut(nums[right],0)+1);
        while(map.lastKey()- map.firstKey() > limit) {
            map.put(nums[left],map.get(nums[left])-1);
            if(map.get(nums[left]) == 0) {
                map.remove(nums[left]);
            }
            left++;
        }
        ret = Math.max(ret, right - left +1);
        right++;
    }
}
//随便一个数组,需要的什么呢?有一个limit数值。

滑动window中的中位数

问题有1,对数据的延迟删除的。2,有一个makeBalance的问题是什么?需要不断的对数据的中点的移动啊。
对数据的处理呢?有的问题是说数据流进了。

public class Leet0203 {
    public double[] medianWindow(int[] nums, int k) {
        DualHeap dh = new DualHeap(k);
        for (int i = 0; i < k; i++) {
            dh.insert(nums[i]);
        }
        double[] ans = new double[nums.length-k+1];
        ans[0] = dh.getMedian();
        /*why */
        for (int i = k; i < nums.length; i++) {
            dh.insert(nums[i]);
            dh.erase(nums[i-k]);
            ans[i-k+1] = dh.getMedian();
        }
        return ans;
    }

    /*自己的问题是说?
    * 1, 为啥要维持主的是delayed的map元素?
    * */

    private class DualHeap{
        int k;
        /*大根:元素小的一部分了*/
        PriorityQueue<Integer> small;
        /*小根:元素大的一部分的元素了*/
        PriorityQueue<Integer> large;
        /*why???*/
        Map<Integer, Integer> delayed;
        private int smallSize, largeSize;
        public DualHeap(int k) {
            this.k = k;
            /**@对于他的比较就是说。有-1就是小于的。默认是-1
             *
             * 就是一个降序的排序了;
             * */
            this.small = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    /*原来如此、底层要的是
                    * @{pre < post element}
                    * */
                    return o2.compareTo(o1);
                }
            });
            /*
            *升序了,需要的是什么呢?*/
            this.large = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1.compareTo(o2);
                }
            });
            this.smallSize = 0;
            this.largeSize= 0;
            this.delayed = new HashMap<>();
        }

        public double getMedian() {
            return (k & 1) == 1 ? small.peek() :((double) small.peek()+large.peek())/2;
        }

        public void insert(int num) {
            if (small.isEmpty() || num< small.peek()) {
                small.offer(num);
                ++smallSize;
            } else {
                large.offer(num);
                ++largeSize;
            }
            makeBalance();
        }

        /**@需要自己对数据的模拟啊,不要这样因为我们知道,优先队列是不支持移出非堆顶元素这一操作的,
        因此我们可以考虑使用「延迟删除」的技巧,即:就会出现了delayed的东西了.*/

        public void erase(int num) {
            delayed.put(num, delayed.getOrDefault(num,0) +1);
            if (num < small.peek()) {
                --smallSize;
                if (num == small.peek()) {
                    prune(small);
                }
            }else {
                --largeSize;
                if (num == large.peek()) {
                    prune(large);
                }
            }
            makeBalance();
        }

        /*function is to ? pop the heap element, and update the map
        * 在 \texttt{prune(heap)}prune(heap)
        * 完成之后,我们就可以保证 \textit{heap}heap
        * 的堆顶元素是不需要被「延迟删除」的。
        * */
        public void prune(PriorityQueue<Integer> heap){
            while(!heap.isEmpty()) {
                /*延迟的删除,对要删除的尽量*/
                int num = heap.peek();
                if (delayed.containsKey(num)){
                    delayed.put(num, delayed.get(num)-1);
                    if (delayed.get(num) == 0) {
                        delayed.remove(num);
                    }
                    heap.poll();
                } else{
                    break;
                }
            }
        }

        public void makeBalance(){
            if (smallSize > largeSize+1) {
                large.offer(small.poll());
                --smallSize;
                ++largeSize;
                /*small的peek有问题的*/
                prune(small);
            } else if (smallSize < largeSize){
                small.offer(large.poll());
                ++smallSize;
                --largeSize;
                prune(large);
            }
        }
    }
}

字母在区间内的出现问题了

至少k个重复字母

有利用的是less。表明在lr的区间内有多少的字母没有达到k个字母了。

 public int longestSubstringAnswer(String s, int k) {
        int ret = 0;
        int n = s.length();
        for (int t = 1; t <= 26 ; t++) {
            int l = 0, r = 0;
            int[] cnt = new int[26];
            int tot = 0;
            int less = 0;
            while (r < n) {
                cnt[s.charAt(r)-'a']++;
                if (cnt[s.charAt(r)-'a'] == 1) {
                    tot++;
                    less++;
                }
                if (cnt[s.charAt(r)-'a'] == k) {
                    less--;
                }
                while(tot > t) {
                    cnt[s.charAt(l)-'a']--;
                    if (cnt[s.charAt(l)-'a'] == 0) {
                        tot--;
                        less--;
                    }
                }
                l++;
            }
            if (less == 0) {
                ret = Math.max(ret, r-l+1);
            }
            r++;
        }
        return ret;
    }