leetcode/lintcode刷题系-Sliding Window Median

Sliding Window Median

Question: Given an array of n integer, and a moving window(size k), move the window at each iteration from the start of the array, find the median of the element inside the window at each moving. (If there are even numbers in the array, return the N/2-th number after sorting the element in the window. )

ExampleFor array [1,2,7,8,5], moving window size k = 3. return [2,7,7]At first the window is at the start of the array like this[ | 1,2,7 | ,8,5] , return the median 2;then the window move one step forward.[1, | 2,7,8 | ,5], return the median 7;then the window move one step forward again.[1,2, | 7,8,5 | ], return the median 7;

分析:
  1. 首先,这道题目是一道移动窗口求中位数类的问题,对于动态求中位数的问题,通常我会用heap的模版来处理,即维持两个heap,minheap和maxheap,maxheap来存放所有比中位数小的及相等的数+中位数,minheap存放所有比中位数大的数;举例说明,当我们的数组是[1,2,7],这个时候maxheap存放[1,2],minheap存放[7],中位数就是maxheap里的最大值,当有新的数进来或者旧的数出去的时候,我们每次都和当前median的大小来比较,决定放入哪个heap,再根据左右两边size的大小进行相应调整,永远满足median是 N/2-th number。
  2. 选用什么数据结构?因为这里的动态窗口还要求删除被移除窗口的元素,所以我们需要一个数据结构,既能满足heap的性质,又能满足定点删除的性质,于是想到了hashheap!java中TreeSet正好满足。
  3. 这里有一个tricky的点在于,因为input中的输入点可能是duplicated,直接把数放到treeset中,不能存下duplicated elements,怎么解决?想到了可以构造一个class,同时包含这个element在input array的位置,即id,还包含这个element的value,那么我们将得到unique的object。

代码:

public class Solution {
/**
 * @param nums: A list of integers.
 * @return: The median of the element inside the window at each moving.
 */
public Node insertNum(Node median, Node currNode, TreeSet<Node> minheap, TreeSet<Node> maxheap){
    /* median is put on the maxheap */
    if(maxheap.size() == 0 && minheap.size() == 0){
        maxheap.add(currNode);
        return currNode;
    }
    if(currNode.val <= median.val){

        if(maxheap.size()-minheap.size() < 1){
            maxheap.add(currNode);
            median = maxheap.last();
        }else{
            minheap.add(median);
            maxheap.remove(median);
            maxheap.add(currNode);
            median = maxheap.last();
        }
    }else{
        if(maxheap.size() > minheap.size() ){
            minheap.add(currNode);
        }else{
            minheap.add(currNode);
            median = minheap.first();
            maxheap.add(median);
            minheap.remove(median);
        }
    }
    return median;
}

public ArrayList<Integer> medianSlidingWindow(int[] nums, int k) {
    // write your code here
    ArrayList<Integer> list = new ArrayList<Integer>();
    if(nums.length == 0 || k <= 0 || nums.length < k){
        return list;
    }

    TreeSet<Node> minheap = new TreeSet<Node>();
    TreeSet<Node> maxheap = new TreeSet<Node>();

    Node median = new Node(0, nums[0]);
    maxheap.add(median);
    for(int i = 1; i < k; i++){
        Node currNode = new Node(i, nums[i]);
        median = insertNum(median,  currNode, minheap, maxheap);
    }
    list.add(median.val);

    for(int i = k; i < nums.length; i++){
        Node currNode = new Node(i, nums[i]);
        Node prevNode = new Node(i-k, nums[i-k]);
        if (minheap.contains(prevNode)) {
            minheap.remove(prevNode);
        }
        else{
            maxheap.remove(prevNode);
        }

        median = insertNum(median, currNode, minheap, maxheap);
        list.add(median.val);
    }
    return list;
  }

}

/* construct node class */
class Node implements Comparable<Node>{
    int id;
    int val;
    Node(int id, int val){
        this.id = id;
        this.val = val;
    }
    /* construct compareTo method, to make sure the elements is sorted by val or ID when vals are same */
    public int compareTo(Node other){
        if(this.val == other.val){
            return this.id-other.id;
        }
        return this.val-other.val;
    }
}

爬虫中关于登录网页,文件上传的一些笔记

爬虫中遇到的登录login和form

大多数web form都是由一些HTML field, submit button, 以及一个”action” page,即form真正被处理的地方,共同组成。举例说明,以下为一个最基本的web form:http://pythonscraping.com/pages/files/form.html, 可以用chrome浏览器,view-developer-source code查看html代码。

通过查看代码,要注意两点:

  • [ ] 两个input field的名字是firstname和last name, 这两个名字是我们一会儿要POST到server去的。
  • [ ] 这里处理form的文件是processing.php,也是我们一会要传送的。

怎么在爬虫中完成登录,在这里介绍python的Request library,非常简单的代码:

`import requests

params = {‘firstname’: ‘Ryan’, ‘lastname’: ‘Mitchell’}
r = requests.post(“http://pythonscraping.com/files/processing.php“, data = params)
print(r.text)`

当然,这里的例子用的form很简单,但是当面对登录页面复杂的HTML代码时,我们也不用过于紧张,我们只需要寻找两类:

  • [ ] 想要提交的数据的field的名字, 比如上面例子的firstname和lastname。
  • [ ] 真正处理form的action page。

爬虫中遇到的Radio Buttons, Checkboxes和其他输入

标准HTML文件包含了很多可能的form input fields,比如radio buttons, checkboxes, select boxes, 在 HTML5中,还有emails, dates等等,尽管登录页面代码看着很复杂,但我们要集中查找以上谈过的两类:

  • [ ] 想要提交的数据的field的名字, 比如上面例子的firstname和lastname。
  • [ ] 真正处理form的action page。

有一种非常便捷的方法查看GET REQUESTS, 就是查看这个site的url,举例说明:假设url长这样http: //domainname.com?thing1=foo&thing2=bar

上传文件和图片

举例说明操作吧,https://www.pythonscraping.com/files/form2.html, 查看其source code后,我们发现和第一个例子的source code很像,不同点在于这里的 type是file,代码如下:

`import requests

files = {‘uploadFile’: open(‘.,/files/pic.png’, ‘rb’)}
r =requests(“https://www.pythonscraping.com/pages/processing2.php“, files=files)
print(r.text)`

leetcode/lintcode刷题系-Trapping Rain Water 类问题的分析

Trapping Rain Water: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

Example: Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

对于这道灌水题,因为水只有在凹槽中才能储存,因此可以用左右两个指针,一个指着array最左端,一个指着array最右端,分别标记此时左右两端的高度lheight, rheight, 取两个值中的较小值,假设是lheight,这个高度便是我们的“灌水基调”,使这个bar的指针往中间移动,,指向下一个bar,当下一个bar高度小于当前“灌水基调”,那么这个位置是可以储存住水的,两者高度差就是灌水量,而若下一个bar高度大于当前”灌水基调“,那么我们更新lheight为当前bar的高度,进入下一次循环,划线部分重复,直到左右指针相交。

`

public class Solution {
/**
 * @param heights: an array of integers
 * @return: a integer
 */
public int trapRainWater(int[] heights) {
    // write your code here
    /* check if input is valid */
    int left = 0, right = heights.length-1, res = 0;
    if(heights == null || heights.length == 0){
        return res;
    }

    int leftHeight = heights[left];
    int rightHeight = heights[right];
    while(left < right){
        if(leftHeight < rightHeight){
            left++;
            if(heights[left] < leftHeight){
                res += leftHeight-heights[left];
            }else{
                leftHeight = heights[left];
            }
        }else{
            right--;
            if(heights[right] < rightHeight){
                res += rightHeight-heights[right];
            }else{
                rightHeight = heights[right];
            }
        }
    }

    return res;
}

`