Sunday, December 8, 2013

Max Points on a Line !!!!!!!!!!!!!!!!!!

Q:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

A:
现在的思路,就是,先根据slope 分组,  具有相同(很接近)斜率 slope的点放到一组。
然后,对每一组, 再找出具有相同(很接近) 的截距(intersect)的点来。 --记录最大的list的长度,然后返回即可。--------------理论上来讲,是O(n^2)
注意: 重复的点,也算不同的点来count
哎,就TM知道, 不能用这种屌丝办法,会超时,  现在好了,真的超时了。废了一晚上的时间。~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~主要的时间开销,就在Step1 里的双重循环上了。(对每个点,找它的所有的slope),其目的是: 将具有same  slope 的组合 放到一起。(虽然,可能不是相同的节点)
-----------------------------------------代码见本页最后--------------------------------



----------------其实,不是算法复杂度的问题, 是利用了O(n^2)的空间的问题。  也存储了太多的,冗余的slope。------------------------

--------------------------下面是别人的思路-------------------------------------------------
分析:首先要注意的是,输入数组中可能有重复的点。由于两点确定一条直线,一个很直观的解法是计算每两个点形成的直线,然后把相同的直线合并,最后 包含点最多的直线上点的个数就是本题的解。我们知道表示一条直线可以用斜率和y截距两个浮点数(垂直于x轴的直线斜率为无穷大,截距用x截距),同时还需 要保存每条直线上的点(避免重复)。听起来就很麻烦,但是基于这个思想有一种简单的实现方式:
  • 以某点O为中心,计算它和其他点的斜率,如果有两个点A、B和O点形成的斜率相等,那么ABO三点是共线的,如果有多个点和O的斜率相等,那么这 多个点和O也是共线的,因此我们可以求出包含O的所有直线中点数最多的直线,会得到一个最大共线点数k(O),如果和O点重复的点有n个(除了O本身), 那么K(O) = K(O) + n。这一步的计算中,为了提高效率,我们可以用哈希表来保存某个斜率对应的点的数目。
  • 对数组中的每一个点i,按照第一步计算得到每个点最大点数K(i)
  • 从k(i)中选取最大的就是本题的解
  • 注意:为了避免重复计算,以数组中第i个点为中心时,只计算数组中它右边的所有点        

public class MaxPointsOnALine2 {

    public int maxPoints(Point[] points) {
        // for each point, we calculate its slope with others,
        // if they are the same, we save them into a Hashtable
        if (points.length <= 1) { // pay attention to length == 1
            return points.length;
        }
        int nMaxPoints = 0;

        for (int i = 0; i < points.length - 1; i++) {
            // for slope Double, we map its count of integers that could form
            // this slope with points[i]

            Map<Long, Integer> map = new HashMap<Long, Integer>();
            Point pLeft = points[i];
            int nDuplicate = 1; // how many points that having the same (x,y)
                                // value with pLeft(inclusive)
            for (int j = i + 1; j < points.length; j++) {
                Point pRight = points[j];
                if (pLeft.x == pRight.x && pLeft.y == pRight.y) {
                    nDuplicate++;
                    continue;
                } else {
                    Long longSlope;  // is is 10000* actuall slope
                    // calculate their slope and save into a the HashMap
                    if (pLeft.x == pRight.x) {
                        longSlope = Long.MAX_VALUE;
                    } else {
                        double slope = (double) (pRight.y - pLeft.y) / (pRight.x - pLeft.x);
//                        slope = BigDecimal.valueOf(slope).setScale(5, BigDecimal.ROUND_HALF_DOWN)
//                                .doubleValue();// round the slope
                        longSlope =Math.round(slope*10000);
                    }
                    // insert the slope into the hashMap
                    Integer objCount = map.get(longSlope);
                    if (objCount == null) {
                        map.put(longSlope, 1);
                    } else {
                        map.put(longSlope, objCount + 1);
                    }
                }
            }// enf of for loop ---- j
            nMaxPoints = Math.max(nMaxPoints, nDuplicate); // in case that
                                                            // HashMap is empty
            // search all slopes passing pLeft, and update the nMaxPoints
            Iterator<Entry<Long, Integer>> iter = map.entrySet().iterator();
            while (iter.hasNext()) { // for each slope, need find the max point
                Map.Entry<Long, Integer> entry = (Map.Entry<Long, Integer>) iter.next();
                Integer curCount = (Integer) entry.getValue();
                nMaxPoints = Math.max(nMaxPoints, curCount + nDuplicate);
            } // end of while
        } // end of for loop ----- ivalue

        return nMaxPoints;
    }
}

罪魁祸首找到啦~~~~~~~~~~~~~~, 就是
//                        slope = BigDecimal.valueOf(slope).setScale(5, BigDecimal.ROUND_HALF_DOWN)
//                                .doubleValue();// round the slope
把这句话注释掉,就可以了。  ~~~~~~~加上这句话,  运行时间,变成了10倍多。
~~~~~~~~可是,不是说double不能完全一样的值吗???????????
嗯,出现问题了,  去掉这句话之后, 出现  -0.0 和0.0 的slope不一样的问题。怎么办????

解决方法就是: 把double的slope * 10000, 转换成long 类型,就行了。

因此,方法一,也如此解决pass。    具体修改,可以见Eclipse中的代码。  (而且,上面的代码,也没有处理duplicates 的问题。  因此,还是只看解法2吧。


Mistakes:
1:  刚开始,没有考虑,输入数组的长度为0, 为1 的情况。  反而在题目中,直接默认为长度超过2了。  直接调用了, slopeList[0] 啊什么的

2:: 对于slope 为正无穷的情况, 在求 difference  of intersect的时候,要要单独处理,  其各自的intersect 可以用point.x 的值代替。

 3: 注意: 重复的点,也算不同的点来count。  但是,在实际

4: 一开始,设
        double minDiff = 0.0000001;
结果太小了,计算机的round error还是超过了这个值。 更改为
        double minDiff = 0.00001;  

5: 方法二的时候, update nMaxPoints 在第二个for循环后面,而且,刚开始,弄成iter 必须是非空才能update 的。因此,对于输入  ”(0,0),(0,0)“  就不能update nMaxPoints了。


Learned:
1:  round  a double data,   可以用下面的代码:
        double slope = 2.1234567;
        slope = BigDecimal.valueOf(slope).setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue();
        System.out.println(slope);
打印的结果是   2.12346
2:  在leetcode中,也可以在class的前面,加入import 语句。

3: 如何遍历一个HashMap
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry entry = (Map.Entry) iter.next();
    Object key = entry.getKey();
    Object val = entry.getValue();
}
效率高,以后一定要使用此种方式!
3.5------------------另一种方式,更简单 ----------------
HashMap<Integer,Integer> map = new HashSet<Integer,Integer>();
for(int key : map.keySet()
        // do something

4:  表示直线,
First, DO NOT use double in such kind of problem, you don't need them and they will make you suffer, DO use integers
Second, <k, b> is not a good idea simply because you cannot represent all the possible line using it.
You can use <a, b, c> to represent all the possible line, i.e., ax + by + c = 0 where a, b, c are all integers.

--------------------------------------------第二遍-----------------------------------------

没有去遍历map,而直接是在建立的时候,查询并保存了结果。


Big Mistake: 
        当计算斜率的时候,  long / long  的结果是 long 的, 而不是double的, 因此,要想 得到小数的结果, 需要把一个先转换成double类型,  我艹~~~~~~~~~~~~~~~~~~~  你SB,~~~~~脑子坏掉了。 Tiger


import java.util.*;

public class Solution {
    public int maxPoints(Point[] points) {
        if (points.length <= 1)
            return points.length;
        int maxPointOnLine = 0;
        HashMap<Long, Integer> map = new HashMap<Long, Integer>();// map scale to count
        for (int i = 0; i < points.length; i++) {
            map.clear();
            int duplicate = 1;
            int maxCount = 0;
            for (int j = i + 1; j < points.length; j++) {
                Long ratio = 0L;
                if (points[j].x == points[i].x && points[j].y == points[i].y) {
                    duplicate++;
                } else {
                    if (points[j].x == points[i].x)
                        ratio = Long.MAX_VALUE;
                    else
                        ratio = (long) ( (double)(points[j].y - points[i].y) / (points[j].x - points[i].x) * 100000);
                    int count  =1;
                    if (map.get(ratio) != null)
                        count = map.get(ratio) +1;
                    map.put(ratio, count);
                    maxCount = Math.max(maxCount, count);
                }
            }
            maxPointOnLine = Math.max(maxPointOnLine, duplicate + maxCount);
        }
        return maxPointOnLine;
    }
}


错误2 :     2遍都有这个错误。 
另外,  在update maxPointOnLine 的时候, 不能把              maxPointOnLine 放到for  ( int   j) 这个循环的里边, 会导致  update的时候,  count 和 nDuplicate 不同时是最大的。  因此,要放到外边去。里层循环, 记录斜率的maxCount  .

哎,Tiger,先不要节省代码行数, 即使超出30行又能如何? 要保证正确才对。

错误3: 
曾经写过这样   count  = (map.get(key) == null)? 0 : map.get(key)   + 1 ;  这样的结果不是预期的。   不知道为什么  ~~~~~~~~





--------------------------------解法1 的代码(没pass,只代表思路)----------------------

import java.math.BigDecimal;
import java.util.Map;
import java.util.Map.Entry;

public class Solution {
public int maxPoints(Point[] points) {
        // first divided by slope,
        // NOTE: due to the fact that digital numbers cannot be too concise, we
        // use approximatin
        if (points == null || points.length == 0)
            return 0;
        if (points.length == 1)
            return 1;
        double minDiff = 0.00001;
        Map<Double, Integer> map = new HashMap<Double, Integer>();
        // a map from slope into the position of List of Points
        ArrayList<HashSet<Point>> slopeList = new ArrayList<HashSet<Point>>();

        // Step1: for each pair of points, calculte their slope and add them
        // into the hashMap
        for (int i = 0; i < points.length - 1; i++) {
            for (int j = i + 1; j < points.length; j++) {
                Point pLeft = points[i].x < points[j].x ? points[i] : points[j];
                Point pRight = points[i].x >= points[j].x ? points[i] : points[j];
                double slope;
                if (pRight.x - pLeft.x == 0) {
                    slope = Double.MAX_VALUE;
                } else {
                    slope =( (double)(pRight.y - pLeft.y)) / (pRight.x - pLeft.x);
                    slope = BigDecimal.valueOf(slope).setScale(5, BigDecimal.ROUND_HALF_DOWN)
                            .doubleValue();// round the slope
                }
                Integer index = map.get(slope);
                if (index == null) { // if current slope is not found
                    index = slopeList.size();
                    map.put(slope, slopeList.size()); // add at last position
                    HashSet<Point> tmp = new HashSet<Point>();
                    slopeList.add(tmp); // add one element at slopeList
                }
                HashSet<Point> tmpSet = slopeList.get(index);
                tmpSet.add(pLeft);
                tmpSet.add(pRight);
            }
        }

        // Step 2: now all list contains points of same slope, with some of
        // its neighgbors,
        // we try to find , if using same slope, check the intersect difference
        int maxPoints = 0;
        Iterator<Entry<Double, Integer>> iter = map.entrySet().iterator();
        while (iter.hasNext()) { // for each slope, need find the max point
                                    // through a line ,coz they might parrelel
            Map.Entry<Double, Integer> entry = (Map.Entry<Double, Integer>) iter.next();
            Double slope = (Double) entry.getKey();
            Integer index = (Integer) entry.getValue();

            HashSet<Point> curSet = slopeList.get(index);
            if (curSet.size() <= maxPoints) {
                continue;
            }
            // each element contains lists that having same slope and intersect 
            ArrayList<ArrayList<Point>> all = new ArrayList<ArrayList<Point>>();
            for (Point eachPoint : curSet) { // check the difference with
                                                // existing ones
                boolean findGroup = false;
                // check all points in the list, that might belongs to same
                // group
                for (int j = 0; j < all.size(); j++) {
                    // if found the node that with intercept small enough
                    // arraylist, with same slope and same intersect
                    ArrayList<Point> al = all.get(j);
                    double curIntercept, newIntersect;
                    if (slope == Double.MAX_VALUE) {
                        curIntercept = al.get(0).x;
                        newIntersect = eachPoint.x;
                    } else {
                        curIntercept = al.get(0).y - slope * al.get(0).x;
                        newIntersect = eachPoint.y - slope * eachPoint.x;
                    }
                    if (Math.abs(curIntercept - newIntersect) < minDiff) {
                        al.add(eachPoint);
                        findGroup = true;
                        break;
                    }
                }
                // if not find its group, we append this point to all
                if (findGroup == false) {
                    ArrayList<Point> al = new ArrayList<Point>();
                    al.add(eachPoint);
                    all.add(al);
                }
            }
            // find the maximun number of List, for current slope,
            for (int i = 0; i < all.size(); i++) {
                ArrayList<Point> al = all.get(i);
                if (al.size() > maxPoints) {
                    maxPoints = al.size();
                }
            }
        }
        return maxPoints;
    }
}

Saturday, December 7, 2013

String to Integer (atoi)

Q:
Implement atoi to convert a string to an integer.
Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
Requirements for atoi: The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. (这里是句号)
 If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

A:
一开始,竟然没敢把题目看完,就不敢做了。哎,真是可笑,竟然留到了最后才做,这么一道简单的题目。 ╮(╯▽╰)╭    可悲啊, Tiger

思路很简单,就是一个个地数呗。

public class Solution {
   public int atoi(String str) {
        // Note: The Solution object is instantiated only once and is reused by
        // each test case.
        int INT_MAX = 2147483647;
        int INT_MIN = -2147483648;
        StringBuffer buf = new StringBuffer(str.trim());// ignore space at two
                                                        // ends
        int sign = 1;
        if (buf.length() == 0)
            return 0;
        if (buf.charAt(0) == '+') { // delete +
            buf.delete(0,1);
        } else if (buf.charAt(0) == '-') {
            sign = -1;
            buf.delete(0, 1);
        }
        str = buf.toString();
        long sum = 0;
        // adding from back to begin
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (ch < '0' || ch > '9')
                break;
            int val = ch - '0';
            sum = sum * 10 + val;
            if (sign == 1) {
                if (sum > INT_MAX) {
                    return  INT_MAX;
                }
            } else { // sum should be negative
                if (sign * sum < INT_MIN) {
                    return   INT_MIN;
                }
            }
        }
        return (int) (sign * sum);

    }
}



Mistakes:
1:  题意理解错误, : 当超出范围时, 返回最大或最小的。 而不是返回  0.
2;  自己宽泛了题意。 当 + -符合后面,是不能再有空格的。

1: 要注意:
return (int) (sign * sum);   这里, 由于sum 是long 型的,   如果仅仅写成
return (int) sign * sum;     是不对的,  会先只转变 sign 的类型。    


--------------第二遍--------------
1: 刚开始,直接开始 考虑str[0] 的值。  而没有先考虑,是否存在 0 位置。

*********************每次计算之前判断是否越界****************

public class Solution { 
    public int myAtoi(String str) {
        boolean isNeg = false;
        str = str.trim();
        if(str.length()==0)
            return 0;
        if(str.charAt(0)=='+' || str.charAt(0)=='-'){
            isNeg = str.charAt(0)=='-';
            str = str.substring(1);
        }
        int sum = 0;
        for(int i =0;i<str.length();i++){
            char ch = str.charAt(i);
            if(Character.isDigit(ch)==false)
                break;
            if(isNeg && (sum < Integer.MIN_VALUE/10 || (sum == Integer.MIN_VALUE/10 && ch>= '8') ))
                return Integer.MIN_VALUE;
            if( !isNeg && (-sum > Integer.MAX_VALUE/10  || ( -sum == Integer.MAX_VALUE/10  && ch>='7')))
                return Integer.MAX_VALUE;
            sum = sum * 10 - (ch -'0');
        }
        return isNeg?sum:-sum;
    }
}

这里,或者直接用long 来记录结果,然后对比即可。

146. LRU Cache -------M !!!!!!!!!!!

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
The cache is initialized with a positive capacity.
Follow up:
Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

A:

------------------用doubly-linked list做更新 + HashMap 来做cache---------
class LRUCache {
public:
    LRUCache(int capacity) {        
        cap = capacity;
        header = new Node(0,0);
        tail = new Node(0,0);
        header->next = tail;
        tail->pre = header;
    }
    
    int get(int key) {
        if(map.find(key)==map.end()){
            return -1;
        }
        Node* tmp = map[key];
        detachAndPutBegin(tmp);
        return tmp->val;
    }
    
    void put(int key, int value) {
        Node * tmp;
        if(map.find(key) == map.end()){
            tmp = new Node(key, value);
            if(map.size()==cap){
                auto delNode = tail->pre;
                delNode->pre->next = tail;
                tail->pre = delNode->pre;
                map.erase(delNode->key);
                delete(delNode);
            }
            map.insert({key, tmp});
            // insert at the begining of the list
            detachAndPutBegin(tmp);
        }else{
            map[key]->val = value;
            tmp = map[key];
            detachAndPutBegin(tmp);
        }
    }
private:    
    struct Node{
        int key, val; // need key to point back to delete the last Node* from map
        Node *pre, *next;
        Node(int key, int v):key(key), val(v), pre(NULL),next(NULL){}
    };
    Node *header, *tail;
    int cap =0;
    unordered_map<int,Node*> map;
    
    int detachAndPutBegin(Node * tmp){
        if(tmp->next){ // if in the list
            tmp->pre->next = tmp->next;
            tmp->next->pre = tmp->pre;
        }        
        // insert into the beginning of the list
        tmp->next = header->next;
        tmp->pre = header;
        header->next->pre = tmp;
        header->next = tmp;
        return tmp->val;
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */


Mistakes:
1:刚开始 删除list的时候,是在Dlist中做的。  可是,还需要把HashMap里的也删掉。

2:   考虑到要在Map中删除节点, 可是,Map只能按照Key 来删。
而我们在ListNode中,每次要删的是最后一个Node,  因此,我们需要在Node中保存每个点的key 值。

还有一个trick 就是double linked list 的前后都加了dummy 节点。这样就不需要处理边界情况。

Wednesday, December 4, 2013

Maximal Rectangle !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Q:
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.

A:
简单的seading算法,(就是假装某点为左上角的corner,然后grow) 应该是太慢了。要注意利用rectangle这个词儿。------------O(n^3)

哎,学会了就行了。 那么纠结干啥?
你就是费劲巴力自己做出来, 有个屁用啊?Tiger, 你SB
这道题,是自己直接上网搜的思路。  看这里, 和这里
具体就是:利用求histogram的思路, 一层层地求最大面积。
 build a cache to make this problem to a list of "Largest Rectangle in Histogram" in M layers 
will take O(M*N^2) time and O(M) space

--------------------第二遍------------------

public class Solution {
    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0)
            return 0;
        int m = matrix.length, n = matrix[0].length,maxArea = 0;
        int[] hist = new int[n];
        for (int i = 0; i < m; i++) { // for each row
            for (int j = 0; j < n; j++)
                hist[j] = matrix[i][j] == '0'? 0: hist[j]+1 ;
            maxArea = Math.max(maxArea, getMaxArea(hist));
        }
        return maxArea;
    }
    public int getMaxArea(int[] hist) { // calculate the max-area of a histogram
        int maxArea = 0, n = hist.length;
        Stack<int[]> stack = new Stack<>();
        for (int i = 0; i < n; i++) {
            int preIndex = i;
            while( ! stack.isEmpty()){
                int[] tmp = stack.peek();
                if( hist[i] < tmp[1]  ){ // calculate area before i
                    stack.pop();
                    maxArea = Math.max(maxArea, tmp[1] * (i-tmp[0]));
                    preIndex = tmp[0];
                }else{
                    break;
                }
            }
            stack.push( new int[]{preIndex,hist[i]} );
        }
        while( ! stack.isEmpty() ){
            int[] tmp = stack.pop();
            maxArea = Math.max(maxArea, tmp[1] * (n-tmp[0]) );
        }
        return maxArea;
    }
}


Mistakes:
这里的核心还是利用histgram 求矩形面积。
其难点在2个地方:
1: 每次发现一个更高的, 则push stack。 否则,计算其前面的比他小的矩形的面积(不包括现在的位置)    2:  计算完毕,重新push的时候,需要存入 最远的index,和现在的高度。(因此我们需要记录 preIndex)  


Learned:
1: 用极大化思想解决最大子矩形问题


Thursday, November 28, 2013

32. Longest Valid Parentheses ---------H

Q:
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2.
Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

A:

 ---------------4th pass ----split into two round,  first find matching position of  ')' ,  and then combine them 

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        vector<int> matched(n, -1);
        vector<int> stack; // stack of non matched (
        for(int i =0;i<n;i++){
            if(s[i] == '('){
                stack.push_back(i);
            }else{
                if(not stack.empty()){
                    matched[i] = stack.back();
                    stack.pop_back();
                }
            }
        }
        // find the left most match
        int res = 0;
        for(int i= 0;i<n;i++){
            if(matched[i] >=0){
                int pre = matched[i];
                if(pre-1>=0 && matched[pre-1] >=0){
                    pre = matched[pre-1];
                }
                matched[i] = pre; // this need UPDATED
                res = max(res, i - pre + 1);
            }
        }
        return res;
    }
};

直觉就是用DP算法。
把输入,从empty的情况,开始加入。来看待。
记录下来,与之匹配的left parentheses的位置。  最后,再计算总长度。


---------------------------第二遍-----------------O(n)的复杂度-----即使是()()的向后跳的情况,也是最多发生O(n)次------------------------
思想是: 从后向前,记录一个该点最远可以达到的距离。
以后每一个新的位置 i ,如果是‘(’  首先找到它的match位置,(可能是 i+1 ,也可能是 farestMatch[i] +1 处)   。
找到match后,再查看是否是()()()这种情况, 并且加上。

public class Solution {
    public int longestValidParentheses(String s) {
        if (s == null || s.length() == 0)
            return 0;
        int n = s.length();
        int[] farestMatch = new int[n];
        for (int i = 0; i < n; i++)
            farestMatch[i] = -1;

        // count from back, at each potision,record farest matching position
        int maxLength = 0;
        for (int i = n - 2; i >= 0; i--) {
            if (s.charAt(i) == '(') {
                // if next position does NOT has its matching
                int k = i + 1;// to be next tested position
                if (farestMatch[i + 1] > 0) // if i+1 position already has it
                                            // matching
                    k = farestMatch[i + 1] + 1;
                if (k < n && s.charAt(k) == ')') {
                    farestMatch[i] = k;
                    // now add possible ()()()() loops
                    while (farestMatch[i] + 1 < n && farestMatch[farestMatch[i] + 1] > 0)
                        farestMatch[i] = farestMatch[farestMatch[i] + 1];

                    maxLength = Math.max(maxLength, farestMatch[i] - i + 1);
                }
            }
        }
        return maxLength;
    }
}

----------------------------3rd Pass-------------------------------------
这次是彻底的O(n)。  而不用那个while 循环。
思想是:  用一个数组,记录其到最左端match 的位置。
          遍历的时候,用stack,记录其前一个match的位置。  然后,每次combine前一个,即得到所有的,最长的match的长度。

public class Solution {
    public int longestValidParentheses(String s) {
        int res = 0,  n = s.length();
        int [] A = new int[n]; // remember A[i]'s furthest matching position
        Arrays.fill(A,-1);
        for(int i =1;i<n;i++){
            if(s.charAt(i) ==')'){
                int pre = i-1;
                if(A[pre] >=  0) // pre position has no match
                    pre = A[pre]-1;
                if(pre>=0 && s.charAt(pre)=='('){
                    A[i] = pre;
                    if(pre-1>=0 && A[pre-1]>=0)
                        A[i] = A[pre-1];
                    res = Math.max(res, i-A[i]+1);
                }
            }
        }
        return res;
    }
}




Mistakes:
1:  当最终计算最大长度的时候,  我随手写了个    if (mostLeftMatchPos[i] > 0 ){
但是, 应该,是    if (mostLeftMatchPos[i] >= 0 ){ 的。
哎,不知道为什么,当时能那样写。
2: 开始, 当输入  为“())的时候,陷入了死循环。
原因是当回头看到的是  与left 没有匹配的情况的时候。  光记得 update nRightMinusLeft 去了, 忘了把j的位置再减一。
3: 当计算longest的时候, 光考虑与之前的单独match了,却没有考虑输入为 “()() ”的情况。
因此,需要在for循环里加一个while语句。



Learned:
1:  不要想着, 精简代码。  重要的,是思路清楚。  最好是(只要复杂度不变) 先解决小问题。不要想着一步到位。  做正确才是最重要的。
例如,这里,刚开始,不要想着, 直接建立leftMostMatch 而,仅仅去找leftMatch即可。
至于()()这种情况。我们完全可以基于leftMatch数组再计算。


130. Surrounded Regions -M

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.
A region is captured by flipping all 'O's into 'X's in that surrounded region.
Example:
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
Explanation:
Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically.

A:

用图像里的growing思想呗。 每碰到一个 o  就开始检测。直到出了边界或者确认包围(转换成X)  嗯,首先是把边界的设 为 标识 @ , 然后grow,
 虽然,也用了小技巧,来提速,但是,这个的实现,还是有点儿慢了。 具体实现,在最后(learned section的下面)

下面这个方法,是利用grow un-surrouned O, 方法。
简单来讲,就是先从四周开始,一层层地剥开。
但是,这样的假设是不成立的, 原因在于, 无法回溯到 zig-zag形式的。

哎,还是回到前面的思路, 考虑到,我们是对200*200的一个巨大的0闭环内没有通过。
我们考虑从四周开始grow un-surrouned region(也就是把上面的2个思路并起来。


class Solution {
public:
    void solve(vector<vector<char>>& board) {
        int m = board.size();
        if(m==0)
            return;
        int n = board[0].size();        
        vector<vector<int> > stack;
        for(int i =0;i<m;++i)
            for(int j =0;j<n;++j)
                if((i==0 || i==m-1 || j==0 || j==n-1 ) && board[i][j] =='O')
                    stack.push_back(vector<int>{i,j});
        // change boundary 'O' --> 'A',
        while(not stack.empty())
        {
            vector<vector<int>> newS;
            for(auto tmp : stack)
            {
                int i = tmp[0], j = tmp[1];
                board[i][j] = 'A';
                if(i>0 && board[i-1][j] =='O')
                    newS.push_back(vector<int>{i-1,j});
                if(i+1<m && board[i+1][j] =='O')
                    newS.push_back(vector<int>{i+1,j});
                if(j>0 && board[i][j-1] =='O')
                    newS.push_back(vector<int>{i,j-1});
                if(j+1<n && board[i][j+1] =='O')
                    newS.push_back(vector<int>{i,j+1});
            }
            stack = newS;
        }
        for(int i =0;i<m;++i)
            for(int j =0;j<n;++j)
                if(board[i][j]=='O')
                    board[i][j] = 'X';
                else if(board[i][j] == 'A')
                    board[i][j] = 'O';
        
    }
};


Mistakes:
2: 处于速度考虑,我们search的时候,尽量通过从4个边来,从内往里search???
3: 还是有一些拼写错误,  主要来自于copy 上面的代码(因为重复性太多)

----------------------------这个更改,删掉了copy vector这个步骤, 节省了空间-------------
class Solution {
public:
    void solve(vector<vector<char>>& board) {
        int m = board.size();
        if(m==0)
            return;
        int n = board[0].size();        
        vector<vector<int> > posList;
        for(int i =0;i<m;++i)
            for(int j =0;j<n;++j)
                if((i==0 || i==m-1 || j==0 || j==n-1 ) && board[i][j] =='O')
                    posList.push_back(vector<int>{i,j});
        // change boundary 'O' --> 'A',
        for(int cur = 0;cur<posList.size();++cur)
        {
            int i = posList[cur][0], j = posList[cur][1];
            board[i][j] = 'A';
            if(i>0 && board[i-1][j] =='O')
                posList.push_back(vector<int>{i-1,j});
            if(i+1<m && board[i+1][j] =='O')
                posList.push_back(vector<int>{i+1,j});
            if(j>0 && board[i][j-1] =='O')
                posList.push_back(vector<int>{i,j-1});
            if(j+1<n && board[i][j+1] =='O')
                posList.push_back(vector<int>{i,j+1});
        }
        for(int i =0;i<m;++i)
            for(int j =0;j<n;++j)
                if(board[i][j]=='O')
                    board[i][j] = 'X';
                else if(board[i][j] == 'A')
                    board[i][j] = 'O';
    }
};



Learned:
1: 在将就效率的时候,就不要搞些递归, 尽量用interative,  来存储中间数据。


--------------下面的这个,too  slow----------coz  we have use too many dfs ---------
public class Solution {
    public void solve(char[][] board) {
        if (board == null || board.length == 0)
            return;
        int m = board.length;
        int n = board[0].length;
        // DFS track the border
        // for first and last rows
        for (int j = 0; j < n; j++) {
            dfs(board, 0, j);
            dfs(board, m - 1, j);
        }
        // for most left and most right columns
        for (int i = 1; i < m - 1; i++) {
            dfs(board, i, 0);
            dfs(board, i, n - 1);
        }
        // flip all inner O into X , and boarder @ into O
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (board[i][j] == 'O')
                    board[i][j] = 'X';
                else if (board[i][j] == '@')
                    board[i][j] = 'O';
    }

    private void dfs(char[][] board, int i, int j) {
        if (board[i][j] != 'O')
            return;
        board[i][j] = '@'; // set as a flag
        int m = board.length;
        int n = board[0].length;

        if (i - 1 >= 0 && board[i - 1][j] == 'O')// up
            dfs(board, i - 1, j);
        if (i + 1 < m && board[i + 1][j] == 'O')// down
            dfs(board, i + 1, j);
        if (j - 1 >= 0 && board[i][j - 1] == 'O')// left
            dfs(board, i, j - 1);
        if (j + 1 < n && board[i][j + 1] == 'O')// right
            dfs(board, i, j + 1);
    }
}

Wednesday, November 27, 2013

150. Evaluate Reverse Polish Notation

Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +-*/. Each operand may be an integer or another expression.
Note:
  • Division between two integers should truncate toward zero.
  • The given RPN expression is always valid. That means the expression would always evaluate to a result and there won't be any divide by zero operation.
Example 1:
Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Example 2:
Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6
Example 3:
Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

A:

       每遇到运算符,就提出最后面的两个,运算,并保存。

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> mystack;
        for(auto s:tokens)
        {
            if(s == "+" || s == "-" || s == "*" || s == "/")
            {
                int a = mystack.top();
                mystack.pop();
                int b = mystack.top();
                mystack.pop();
                if(s == "+")
                    mystack.push(b+a);
                if(s == "-")
                    mystack.push(b-a);
                if(s == "*")
                    mystack.push(b*a);
                if(s == "/")
                    mystack.push(b/a);
            }else{
                mystack.push(stoi(s));
            }
        }
        return mystack.top();
    }
};

Mistakes:
1 : 没有考虑 当一个数为:负数的时候, 例如 -2,  如果只检查首字母, 就会误认为是运算符。
2: 刚开始,自以为是了。  用double类型保持中间值。
    没想到,作者是不用的。   用int数组就行。

----------第二遍-----------
3: 由于是从 + 的情况直接copy 的代码,  对于 -   / 的情况,没有考虑 a,b 的顺序要调过来的。


Learned:





Tuesday, November 26, 2013

148. Sort List -M

Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3
Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0
Output: -1->0->3->4->5

A:

----------------------------merge sort   ---------------------------
First divide into two list, and merge them (append to the end of a new list) , which is of O(n) complexity.
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(not head || not head->next)
           return head;
        //divide into two list
        ListNode* slow = head, *fast = head->next;
        while(not fast && fast->next)      // this is what you made mistake
        {
            slow = slow->next;
            fast = fast->next;
            if(fast)
                fast=fast->next;
        }
        auto p1 = sortList(slow->next);
        slow->next = NULL;
        auto p2 = sortList(head);
        return merge(p1,p2);
    }
private:
    ListNode* merge(ListNode* p1, ListNode* p2)
    {
        ListNode* pre = new ListNode(0);
        ListNode* tail = pre;
        while(p1 || p2)
        {
            if(not p1)
            {
                tail->next = p2;
                break;
            }
            if(not p2)
            {
                tail->next = p1;
                break;
            }
            if(p1->val <p2->val)
            {
                tail->next = p1;
                p1 = p1->next;
            }else{
                tail->next = p2;
                p2 = p2->next;
            }
            tail = tail->next;
        }
        return pre->next;
    }
};







Mistakes: 

2: when updating runner after a while loop, always remember to set runner= runner.next; after extracting Header2 list.

 3: Coz we forget updating the tail  even after we already done inserting the list.
 4:  日!!!!!!
 刚开始, return 命令行上面的一句:         header= newHeader; 应该写成
        header.next = newHeader.next;  就对了。
╮(╯▽╰)╭, 基础不行啊。Tiger ,这种SB的问题,你都能犯~~~~~~ 搞了爷们儿2个小时。 艹


Learned:
1: in C++,  to judge whether a node is null, we have 3 method
       a)  node == NULL
       b)  ! node
       c) not node


Monday, November 25, 2013

Insertion Sort List

Q:
Sort a linked list using insertion sort.
A:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode insertionSortList(ListNode head) {
        ListNode header = new ListNode(Integer.MIN_VALUE);
        while(head!=null){
            ListNode tmp = head;
            head = head.next;
            
            ListNode runner = header;
            while(runner.next!=null && runner.next.val < tmp.val)
                runner = runner.next;
            
            tmp.next = runner.next;
            runner.next = tmp;
        }
        return header.next;
    }
}

Mistakes:
1: 当插入到比tail更前的的时候,  忘了break来跳出循环。
---------------第二遍--------------
1: 忘了把preNode 在whileloop的时候,先置为 newHeader
2:  after  checking preNode == null,    Mistakenly wrote
 tmp.next = preNode.next.next ;                        what the hell, can you make this mistake???????

Learned:



Friday, November 8, 2013

Wildcard Matching ~~~~~~~~~~~~~~~~~~~~~~~

Implement wildcard pattern matching with support for '?' and '*'.
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
A:
1: 先用递归,估计会嫌太慢。先做出来再说吧。

 嗯,确实很慢。问题主要出在* 上。 下面是递归的解法。

public class Solution {
    public boolean isMatch(String s, String p) {
        if(s.length() ==0){
            if(p.length()==0)
                return true;
            else
                return p.charAt(0) =='*'? isMatch(s, p.substring(1)) : false;
        }
        if(p.length() ==0)
            return false;

        if(s.charAt(0) == p.charAt(0) || p.charAt(0) == '?')
            return isMatch(s.substring(1), p.substring(1));
        else if( p.charAt(0) == '*' )
            return isMatch(s,p.substring(1)) || isMatch(s.substring(1),p);
        else
            return false;
    }
}
上面这个解法,对于输入:
"babbbaabbaaaaabbababaaaabbbbbbbbbbabbaaaabbababbabaa", "**a****a**b***ab***a*bab" 
就会严重超时。

问题就出在 倒数第二个return 语句上,|| 后面那个helper()。当s只match了一个。这样效率很低。

  Solution 2
贪心算法,只需要依据连续的’*',将p分割成一些不带’*'的子串。然后在s中依次匹配就好了,只不过需要特殊照顾一下首尾两个子串:
1.对于开头不是’*'的p,第一个子串必须从s[0]开始匹配
2.对于结尾不是’*'的p,最后一个子串必须在s的尾巴上匹配

--------------------------确实快了很多,可是,当*后面的第一个字符串(非通配符)在s中match的次数过多的时候, 速度会显著降低。-------------------这时候,我们就不需要匹配所有的。 只需要找到匹配的即可。 嗯,如果是最后的字串,需要匹配最后的位置。
还需要继续优化。




-------------------solution 3 -----------------------
我们提出solution 3,  也就是把? 和其余的字符串放一起。
因此, p = "a???*a??b"被我们分成  [a,  ???, * ,   a??b] 四个子pattern。 这样出了第一个前面没有*外, 别的子pattern前面都有*, 可以随便移动位置。 (当然,需要自己写 字符匹配的函数。这个很简单)
 ----------------这里深入分析了8种解法----------- (还有代码)
--------------------- 这是第二遍的实现--------------思路跟solution3 一样-------只是更简洁了----

public class Solution {
    public boolean isMatch(String s, String p) {
        if (s == null || p == null) // should not occur
            return false;
        if (s.length() == 0)
            return p.length() == 0 || (p.length() == 1 && p.charAt(0) == '*');
        if (p.length() == 0)// if run this line, s.length() != 0
            return false;
        // check the first is *
        if (p.charAt(0) != '*') {
            int firstStartIndex = p.indexOf("*");
            if (firstStartIndex < 0) { // if p does not contains *
                return s.length() == p.length() && findFirstMatch(s, p) == 0;
            } else { // / p contains *
                String partP = p.substring(0, firstStartIndex);
                int matchPos = findFirstMatch(s, partP);
                if (matchPos != 0) { // if not fint at the first place
                    return false;
                } else { // we have find match at first place
                    s = s.substring(partP.length());
                    p = p.substring(partP.length());
                }
            }
        }
        String[] patternP = p.split("\\*");
        // all patternP[i] have a * ahead
        for (int i = 0; i < patternP.length; i++) {
            String nonStarP = patternP[i];
            int matchPos = findFirstMatch(s, nonStarP);
            if (matchPos < 0) {
                return false;
            } else {
                s = s.substring(matchPos + nonStarP.length());
            }
        }
        // if last have *,  or s is all matched
        return p.charAt(p.length() - 1) == '*' || s.length() == 0;
    }

    private int findFirstMatch(String s, String p) {
        // p does not contains *
        for (int i = 0; i <= s.length() - p.length(); i++) {
            // test substirng and p
            boolean isMatch = true;
            for (int j = 0; j < p.length(); j++) {
                char chS = s.charAt(i + j);
                char chP = p.charAt(j);
                if (chP != '?' && chS != chP) {
                    isMatch = false;
                    break;
                }
            }
            if (isMatch) { // if found match
                return i;
            }
        }
        return -1;
    }
}


Mistakes:
1: 当方法2的时候,没有考虑这种情况
Input: "", ""
Output: false
Expected: true
2:方法2的时候, 由于没有考虑到 p = "*"的情况。
而我们初始条件的startIndex = 0 是第一个valid情况。 而每次startIndex跳到下一个情况(或者越出右边界一位)
这样,就产生了错误。

3: 在用s的startIndex ==0 的初始情况的时候,没有考虑,当s为空的情况。 导致error.

4: when the substring is "?", at first ,we simply skip to next, but it is WRONG. we need also check whether s has the character with it.

5: 当遇到?的时候,我们仅仅startIndex跳到下一个了, 可是,没有注意
s="aa"
p ="*?"的情况时,我们需要多跳几个。  因此,还是需要把*?的顺序,调整成?*

Learned:
1: 好像在leetcode里,不用考虑,输入是null  的情况。
2:
         s = "aa";
         System.out.println( s.lastIndexOf("a", 0));
这里,很诡异的,输出竟然是0  而不是1.  ----------------原因如下。
public int lastIndexOf(String str, int fromIndex)
Returns the index within this string of the last occurrence of the specified substring, searching backward starting at the specified index. 


 -----------------第二遍-----------
1: 用 * 来split ,  命令要写成:   str.split("\\*");    -------- 要用双反斜线
2: 注意, split函数,是可以得到数组的某个元素为 “”的。


  --------------------------------下面 是 别人的代码------------ C++------------

Analysis:

For each element in s
If *s==*p or *p == ? which means this is a match, then goes to next element s++ p++.
If p=='*', this is also a match, but one or many chars may be available, so let us save this *'s position and the matched s position.
If not match, then we check if there is a * previously showed up,
       if there is no *,  return false;
       if there is an *,  we set current p to the next element of *, and set current s to the next saved s position.

e.g.

abed
?b*d**

a=?, go on, b=b, go on,
e=*, save * position star=3, save s position ss = 3, p++
e!=d,  check if there was a *, yes, ss++, s=ss; p=star+1
d=d, go on, meet the end.
check the rest element in p, if all are *, true, else false;

Note that in char array, the last is NOT NULL, to check the end, use  "*p"  or "*p=='\0'".
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        const char* star=NULL;
        const char* ss=s;
        while (*s){
            if ((*p=='?')||(*p==*s)){s++;p++;continue;}
            if (*p=='*'){star=p++; ss=s;continue;}
            if (star){ p = star+1; s=++ss;continue;}
            return false;
        }
        while (*p=='*'){p++;}
        return !*p;
    }
};


-------------------------------------------------第三遍----------------想利用上面的想法, 也用递归来做的。结果还是超时。----------------------------然后就又是按照* 来split,然后线性查找即可--------  因此,这道题目,复杂度应该是在O(n)的--------------

对于前后的non- start string 的问题,我们事先匹配后,消去即可。

public class Solution { 
    public boolean isMatch(String s, String p) {
        if(p.length()==0)
            return s.length()==0;
        if(s.length()==0)
            return p.charAt(0)=='*' && isMatch(s,p.substring(1));
        if(p.charAt(0) !='*'){// delete all before first *
            return (p.charAt(0)=='?' || p.charAt(0)==s.charAt(0)) && isMatch(s.substring(1),p.substring(1));
        }
        if(p.charAt(p.length()-1) !='*'){ // delete all after last *
            char ch = p.charAt(p.length()-1);
            return (ch=='?' || ch ==s.charAt(s.length()-1)) && isMatch(s.substring(0,s.length()-1),p.substring(0,p.length()-1));
        }
        // now at the two end of p,  are *
        String[] P = p.split("\\*");
        int firstMatchPos = 0;
        for(int i =0;i< P.length; i++){
            if( P[i].length()==0)
                continue;
            firstMatchPos = findMatch(s, firstMatchPos,P[i]);
            if(firstMatchPos<0)
                return false;
            firstMatchPos += P[i].length();
        }
        return true;
    }
    private int findMatch(String s, int start, String p){// this p does not contain *
        for(int i =start;i <= s.length()-p.length();i++){
            //check the whole p
            boolean found = true;
            for(int j=0;j<p.length();j++){
                if( p.charAt(j) !='?' && p.charAt(j) != s.charAt(j+i)){
                    found = false;
                }
            }
            if(found)
                return i;
        }
        return -1;
    }
}

-------------------------------又一种思路---------------------
贪心的策略,能匹配就一直往后遍历,匹配不上了就看看前面有没有'*'来救救场,再从'*'后面接着试。
这个解法,其实就是我们最上面的哪种,但是,用两个index而不用递归,大大节省了时间。

public class Solution {
    public boolean isMatch(String s, String p) {
        int i = 0, j = 0;
        int star = -1, mark = -1;
        while (i < s.length()) {
            if (j < p.length()
                    && (p.charAt(j) == '?' || p.charAt(j) == s.charAt(i))) {
                ++i;
                ++j;
            } else if (j < p.length() && p.charAt(j) == '*') {
                star = j++;
                mark = i;
            } else if (star != -1) {
                j = star + 1;
                i = ++mark;
            } else {
                return false;
            }
        }
        while (j < p.length() && p.charAt(j) == '*') {
            ++j;
        }
        return j == p.length();
    }
}



Thursday, November 7, 2013

145. Binary Tree Postorder Traversal -----------M

Given the root of a binary tree, return the postorder traversal of its nodes' values.

Follow up: Recursive solution is trivial, could you do it iteratively?

 

Example 1:

Input: root = [1,null,2,3]
Output: [3,2,1]

Example 2:

Input: root = []
Output: []

Example 3:

Input: root = [1]
Output: [1]

Example 4:

Input: root = [1,2]
Output: [2,1]

Example 5:

Input: root = [1,null,2]
Output: [2,1]

 

Constraints:

  • The number of the nodes in the tree is in the range [0, 100].
  • -100 <= Node.val <= 100
A:
不论是用两个stack (还是每次加到前面,最后reverse回来)原理都是一样的。 
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> S;
        if(root)
            S.push(root);
        
        while(not S.empty()){
            auto cur = S.top();
            S.pop();
            if(cur->left)
                S.push(cur->left);
            if(cur->right)
                S.push(cur->right);
            res.push_back(cur->val);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};


Mistakes:
1: 忘了先check root为null 的情况
--------------------------第三遍------(用了一个stack,一个set(set来记录是否被visited过))--------------------
2:  把if写成了while   ,  哎,丢死人了
3:  写成了先  压栈右边,再压栈左边的了。     这个, 当时是考虑到正常顺序,是要先遍历左子树,再遍历右子树的。   但是, 但是没有考虑到, 其实,我们是reversely 加入到al的最前面的。 因此,  要先遍历右子树的。


public class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
         List<Integer> result = new LinkedList();
         if(root ==null)
            return result;
         Stack<TreeNode> stack = new Stack();
         Set<TreeNode> set = new HashSet();
         stack.push(root);
         set.add(root);
         while(!stack.isEmpty()){
             TreeNode node = stack.pop();
             if(set.contains(node)){// first time to find this node
                stack.push(node);
                if(node.right!=null){
                    stack.push(node.right);
                    set.add(node.right);
                }
                if(node.left!=null){
                    stack.push(node.left);
                    set.add(node.left);
                }
                 set.remove(node);
             }else{// node should be printed directly
                 result.add(node.val);
             }
         }// end of while
         return result;
    }
}


Learned: