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 }

原文地址:https://www.cnblogs.com/hwd9654/p/10917735.html

时间: 2024-08-29 16:36:35

leetcode 352 & leetcode 239 & leetcode 295 & leetcode 53 & leetcode 209的相关文章

[leetcode]352. Data Stream as Disjoint Intervals

数据流合并成区间,每次新来一个数,表示成一个区间,然后在已经保存的区间中进行二分查找,最后结果有3种,插入头部,尾部,中间,插入头部,不管插入哪里,都判断一下左边和右边是否能和当前的数字接起来,我这样提交了,发现错了,想到之前考虑要不要判重,我感觉是这个问题,然后就是在二分查找的时候,判断一下左右区间是否包含当前的值,包含就直接返回. 1 /** 2 * Definition for an interval. 3 * struct Interval { 4 * int start; 5 * in

Leetcode 之Validate Binary Search Tree(53)

判断是否是有效的二叉搜索树,即左子树的值小于根结点,右子树的值大于根结点.可以采用递归的方式来完成,递归时如何 传递有效的参数与根结点进行比较,是此题的难点. 1 bool isValidBST(TreeNode *root) 2 { 3 isValidBST(root, INT_MIN, INT_MAX); 4 } 5 bool isValidBST(TreeNode *root, int lower, int upper) 6 { 7 return (root->val > lower &

笔试题53. LeetCode OJ (40)

这个题目还是nsum类型的,不过比上个题更难.上个题的复杂性不是很高,因为不需要考虑到元素的重复性对结果造成干扰,但这道题的话,还是在"集合"里面找出 nsum = target, 每个元素只能使用一次且最后的结果不能重复.那么对于"集合"里面出现的重复的元素的处理就特别棘手.其实代码和上个题的差不多,其实只多了几行,但是这几行代码我却想了一天,甚至睡觉前还想了一段时间,但是下午在做实验的时候突然大脑一闪,突然想到了思路,我今天刚好想到了二叉树的后续非递归遍历的做法

Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray)

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6. 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解. 定义:dp[i] 表示从起点到index=i的这个段内的最大子序和. 例如:dp[1] = 在[-2,1]这个区间里面的最大子序和,dp[1]=1 写出状态转移方程:dp[i

【LeetCode】Two Sum

Two Sum Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please no

LeetCode解题报告:Reorder List

Reorder List Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do this in-place without altering the nodes' values. For example,Given {1,2,3,4}, reorder it to {1,4,2,3}. 思路: 1.利用快慢两个指针将链表一分为二: 2.针对第二个子链表求倒序

[LeetCode] questions for Dynamic Programming

Questions: [LeetCode] 198. House Robber _Easy tag: Dynamic Programming [LeetCode] 221. Maximal Square _ Medium Tag: Dynamic Programming [LeetCode] 62. Unique Paths_ Medium tag: Dynamic Programming [LeetCode] 64. Minimum Path Sum_Medium tag: Dynamic P

[LeetCode] Encode and Decode TinyURL 编码和解码小URL地址

Note: This is a companion problem to the System Design problem: Design TinyURL. TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl and it returns a short URL such as http://tinyurl.com/4e9iA

[LeetCode] K-th Smallest in Lexicographical Order 字典顺序的第K小数字

Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n. Note: 1 ≤ k ≤ n ≤ 109. Example: Input: n: 13 k: 2 Output: 10 Explanation: The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so