• leetcode 352 & leetcode 239 & leetcode 295 & leetcode 53 & leetcode 209


    lc352 Data Stream as Disjoint Intervals

    可以用treemap解

    key保存interval的start,value保存interval的end。分别找出当前val的lowerKey(treemap中>val的最小key值,没有就返回null)和higherKey(<val的最大key没有就返回null) 有以下几种情况: 1) 当前插入的key与前后两个interval重叠 合并三者,将前一个的interval.end改成后一个的end,并且将后一个从treemap中删除 2) 当前插入的key与前面的interval重叠 合并,前一个interval的end改成Math.max(end, val) 注意这里的判断条件不能写成 treemap.(treemap.lowerKey(val)) == val – 1; 而是应该写成>=,前者会出现异常,举例来说[4, 9] 现在val=7,按前者的判断条件,可能就直接放到case4里了,变成[4, 9]和[7, 7]共存 3) 当前插入的key与后面的interval重叠 put(val, 后一个的end) remove(后一个的key) 4) 当前插入的key不和任何已存在interval重叠,直接插入,按题意value设为key值

    class SummaryRanges {
        TreeMap<Integer, Integer> tree;
        /** Initialize your data structure here. */
        public SummaryRanges() {
            tree = new TreeMap<>();
        }
        
        public void addNum(int val) {
            if(tree.containsKey(val))
                return;
            Integer l = tree.lowerKey(val);
            Integer h = tree.higherKey(val);
            Integer lv = l == null ? null : tree.get(l);
            Integer hv = h == null ? null : tree.get(h);
            
            if(l != null && h != null && lv == val - 1 && h == val + 1){
                //lv = hv;
                tree.put(l, hv);
                tree.remove(h);
            }else if(l != null && lv >= val - 1){
                //lv = val;
                tree.put(l, Math.max(lv, val));
            }else if(h != null && h == val + 1){
                tree.put(val, hv);
                tree.remove(h);
            }else{
                tree.putIfAbsent(val, val);
            }
            
        }
        
        public int[][] getIntervals() {
            Iterator it = tree.keySet().iterator();
            int i = 0;
            int[][] res = new int[tree.size()][2];
            while(it.hasNext()){
                Integer key = (Integer)it.next();
                res[i][0] = key;
                res[i][1] = tree.get(key);
                i++;
            }
            return res;
        }
        /*public int[][] getIntervals() {
            return tree.entrySet()
                    .stream()
                    .map(e -> new int[]{e.getKey(), e.getValue()})
                    .toArray(int[][]::new);
        }*/
    }
    
    /**
     * Your SummaryRanges object will be instantiated and called as such:
     * SummaryRanges obj = new SummaryRanges();
     * obj.addNum(val);
     * int[][] param_2 = obj.getIntervals();
     */

    239 Sliding Window Maximum

    1) 双向队列,时间复杂度o(n)

      a) 维护一个最大长为k(可能实际长度小于k,见b)的双向队列,保证当前队列有序,头元素为最大,这样每次只需要取dq.peek()即可。 怎么保证队列有序其头元素最大呢?每次i迭代后,把队列中没有用的元素剔除。就是把<nums[i]的元素全部剔除,然后把nums[i]的索引i放入队列。 怎么剔除?这里就用到了双向队列,从队尾开始删pollLast() 注意,队列中存放的是index而非值本身,目的是为了下一步b中确定队头元素的位置是否还在window内

      b) 保证队头的元素都来自i-k+1~i,因为这是一个sliding window。 if(dp.peek() < i-k+1) dp.poll() //直接删除队首元素

     1 class Solution {
     2     public int[] maxSlidingWindow(int[] nums, int k) {
     3         if(nums == null ||nums.length == 0)
     4             return nums;
     5         int len = nums.length;
     6         int size = len - k + 1;
     7         
     8         int[] res = new int[size];
     9         Deque<Integer> dq = new ArrayDeque<>();
    10         
    11         
    12         for(int i=0, j=0; i<len; i++){
    13             while(!dq.isEmpty() && dq.peek() < i - k + 1)
    14                 dq.poll();
    15             
    16             while(!dq.isEmpty() && nums[dq.peekLast()] <= nums[i])
    17                 dq.pollLast();
    18             dq.offer(i);
    19             if(i >= k-1)
    20                 res[j++] = nums[dq.peek()];
    21         }
    22         
    23         return res;
    24         
    25     }
    26 }

    2) 最大堆,时间复杂度o(nlogk)

    维护一个大小为k的最大堆,可以把priorityqueue翻转一下即可 PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder()) 每次i迭代,去掉nums[i-k],插入nums[i],然后取堆root元素即可。

    295 Find Median from Data Stream

    用一个最大堆和一个最小堆,最大堆里放历史数据流中前k小的数,最小堆中放剩下的数,数据流总size为偶数,则两个堆大小相等,若为奇数,则最大堆比最小堆多一个数。这样我们median要么是最大堆root值,要么是两个堆root的平均值。

     1 class MedianFinder {
     2         PriorityQueue<Integer> min = new PriorityQueue<>();
     3         PriorityQueue<Integer> max = new PriorityQueue<>(Comparator.reverseOrder());
     4     /** initialize your data structure here. */
     5     public MedianFinder() {
     6         
     7     }
     8     
     9     public void addNum(int num) {
    10         max.offer(num);
    11         min.offer(max.poll());
    12         if(max.size() < min.size())
    13             max.offer(min.poll());
    14     }
    15     
    16     public double findMedian() {
    17         if(max.size() == min.size())
    18             //return (max.poll() + min.poll()) / 2;
    19             //poll() will remove the first element of priorityqueue, but peek() will just retrieve the value and will not remove the element
    20             return (max.peek() +min.peek()) / 2.0;
    21         else
    22             return max.peek();
    23     }
    24 }
    25 
    26 /**
    27  * Your MedianFinder object will be instantiated and called as such:
    28  * MedianFinder obj = new MedianFinder();
    29  * obj.addNum(num);
    30  * double param_2 = obj.findMedian();
    31  */

    53 Maximum Subarray

    用dp解

    dp[i]定义为包含当前i的最大子序列

    递归式:dp[i] = max(dp[i-1], dp[i-1] + nums[i]);

    注意还要用一个max变量保存dp[i]中(i=0~n-1)最大的那个dp[i]

    返回值为max

     1 class Solution {
     2     public int maxSubArray(int[] nums) {
     3         if(nums == null ||nums.length == 0)
     4             return 0;
     5         int len = nums.length;
     6         int[] dp = new int[len];
     7         dp[0] = nums[0];
     8         int max = dp[0];
     9         
    10         for(int i=1; i<len; i++){
    11             dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
    12             max = Math.max(max, dp[i]);
    13         }
    14         //max = Math.max(max, dp[0]);
    15         return max;
    16     }
    17 }

    209 Minimum Size Subarray Sum

    双指针,

    一个指针用来求和,即j-i的所有元素只和,sum += nums[i++]

    一个指针用来减去0-j的元素, sum -= nums[j++] 每当j~i之和>=s,记录j~i的长度,用一个min记录所有ij组合的长度最小值,r然后减去当前j所指元素,j++,直到j~i之和<s

     1 class Solution {
     2     public int minSubArrayLen(int s, int[] nums) {
     3         if(nums == null || nums.length == 0)
     4             return 0;
     5         int i=0, j=0, min = Integer.MAX_VALUE;
     6         int sum = 0;
     7         
     8         while(i < nums.length){
     9             sum += nums[i++];
    10             
    11             while(sum >= s){
    12                 min = Math.min(min, i-j);
    13                 sum -= nums[j++];
    14             }
    15         }
    16         
    17         return min == Integer.MAX_VALUE ? 0 : min;
    18     }
    19     
    20     
    21 }
  • 相关阅读:
    一个晚上加一个上午啊 笨死算球
    转来的——python webdriver自动化测试初步印象——转来的
    MySQL软件升级
    创建rhel7基础镜像
    SHELL-收集Oracle已应用的PSU信息
    rhel7.6上安装Oracle 19.2.0.0 RAC
    AIX平台安装Oracle11gR2数据库
    Oracle Database(rdbms) 12.2 安装组件
    HP-UX平台安装Oracle11gR2数据库
    Linux平台安装Oracle11gR2数据库
  • 原文地址:https://www.cnblogs.com/hwd9654/p/10917735.html
Copyright © 2020-2023  润新知