Friday, November 20, 2015

Board problems

1. Maximal Rectangle in Histogram (Leetcode)

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
The largest rectangle is shown in the shaded area, which has area = 10 unit.
For example,
Given height = [2,1,5,6,2,3],
return 10.

 int largestRectangleArea(vector<int>& height) {
        stack<int>s;
        int area=0;
        int tp;
        int tp_area;
        
        int i=0;
        while (i<height.size()){
            
            if (s.empty()|| height[s.top()]<= height[i]){
                s.push(i);
                i++;
            }else{
                tp=s.top(); s.pop();
                tp_area= height[tp]* (s.empty()? i: i-s.top()-1);
                if( tp_area>area) area= tp_area;
            }
        }
            //remainning:
        while (!s.empty()){
                tp=s.top(); s.pop();
                tp_area= height[tp]* (s.empty()? i: i-s.top()-1);
                if( tp_area>area) area= tp_area;
        }            
        return area;
    }

2. Maximal Rectangle

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.
 
    
    vector<int> hist(vector<vector<char>>& matrix, int line){
        vector<int> ret;
        int M= matrix.size(); 
        int N= M>0? matrix[0].size():0;
        if (!M || !N || line>=M) return ret;
        ret.resize(N,0);
        for (int j=0; j<N; ++j)
            for (int i=line; i>=0; --i){
                    if (matrix[i][j]=='0') break;
                    ret[j]++;
            }
        return ret;
    }

    int maximalRectangle(vector<vector<char>>& matrix) {
        int maxarea=0;
        vector<int> histogram;
        int M= matrix.size(); 
        int N= M>0? matrix[0].size():0;
        if (!M || !N ) return 0;
        for (int i=0; i<M; ++i){
            histogram= hist(matrix, i);
            int local=largestRectangleArea(histogram);
            if (local>maxarea) maxarea= local;
        }
        return maxarea;
    }

Sunday, November 8, 2015

Merge sort, merge lists problems

1. Merge k Sorted Lists [leetcode]

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Solution:  This problem was labelled "hard", but probably it is a medium level.
My first code was to compare lists front every time and did not pass. Then I realized I did not have to compare all every time. A heap will save the job. 
If average length of list is n, # of lists is k, then the complexity is O(n*k*lg(k)) (suppose heap an new element is o(log), which is usually true). Then it passed. 


    class Compare
    {
    public:
        bool operator() (ListNode*a, ListNode*b)
        {
               return a->val>b->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if (lists.empty()) return 0;
        priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
        for (auto &ls: lists){
            if (ls) pq.push(ls);
        }
        
        if (pq.empty()) return nullptr;
        ListNode dummy(0);
        ListNode*cur, *head=&dummy;
        
        while(!pq.empty()){
            cur= pq.top(); pq.pop();
            if (cur->next) pq.push(cur->next);
            head->next=cur;
            head=cur;
        }
        return dummy.next;
    }


2. Merge Two Sorted Lists


Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Solution: nothing more to say, see 
http://charleshuboston.blogspot.com/2015/11/sort-linked-list-in-on-log-n-time-o1.html

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (!l1) return l2;
        if (!l2) return l1;
        //l1 and l2 have nodes
        ListNode*ret ;
        if (l1->val<l2->val){
            ret=l1;
            while (l1->next && l1->next->val<l2->val){
                   l1=l1->next;
            }
            ListNode*l1next= mergeTwoLists(l1->next, l2);
            l1->next=l1next;
            
        }else{
            ret=l2;
            while (l2->next && l2->next->val<=l1->val){
                   l2=l2->next;
            }
            ListNode*l2next= mergeTwoLists(l1, l2->next);
            l2->next=l2next;
        } 
        return ret;

    }

3 Merge Sorted Array[leetcode]

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1and nums2 are m and n respectively.
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
     int pm=m-1, pn=n-1;     
     while (pm>=0 && pn>=0)  
           nums1[pm+pn+1]=nums1[pm]>nums2[pn]?  nums1[pm--]:nums2[pn--]; 

     if (pn==-1) return;
     //copy nums2 remains to nums1
     if (pm==-1) 
         for (int i=0; i<=pn; ++i)
            nums1[i]=nums2[i];
    }

Friday, November 6, 2015

DP problems, sequence problems, grids problem

 1. Longest Increasing Subsequence (LeetCode)
Given an unsorted array of integers, find the length of longest increasing subsequence. (Note: it can jump, skip....only condition is going up) For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
Solution :O(n^2) is easy to figure out. Create DP table from back.  Clearly, the last element only get length 1.  The one before it, if smaller, can get 2; otherwise 1.  The next one before it, can link to whichever later one which is bigger than him, and choose the biggest link. Two nested for loop should do everything. 
//O(n^2)  DP // -- ----- 10, 9, 2, 5, 3, 7, 101, 18 
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) return 0;
        if (nums.size()==1) return 1;
        int global=1;
        vector<int>count(nums.size(),1);        
        for (int i=nums.size()-2;i>=0; --i){
            for (int j=i+1; j<nums.size(); ++j ){
                if (nums[j]>nums[i]){
                    count[i]=max(count[i],count[j]+1);
                }
                if (count[i]>global) global= count[i];
            }
        }
        return global;
    }


2. Edit distance (LeetCode)

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
Solution:  This problem obviously falls in DP category.  Suppose we match "body" to "about". We can start with the end [bod]y ->[abou]t.  
1. If we know [bod]->[abou] best in X time operation,  since 'y' is different with 't', we need X+1;  if we know [body]->[abou] takes Y times, we insert a 't', take Y+1; if we know [bod]->[about] takes Z time, delete 'y', we take Z+1;  We look for min (X+1, Y+1, Z+1)
2. Suppose the last letter is the same, the previous three numbers change to  X, Y+1, Z+1.  We look for min(X,Y+1, Z+1);
3. do not forget to save each cell if we once calculated it.
4. Initialize with 0. That is suppose both word are empty, so we have determined value.   void to void takes 0; void to length 1 ,takes 1...., so row 0 filled with 0->N;  Column 0 filled with 0->M.
5 Before this line, we all assume we do upside down way. We can do bottom up first filling table[1][1], checking word1[0] ->word2[0].
    int act(string src, string dst, int m, int n){
        if (m==0) return n;
        if (n==0) return m;
    
        //(m,n) has three paths  (m-1,n), (m, n-1) (m-1,n-1)
        if (table[m][n]<INT_MAX) return table[m][n];
    
        if (table[m-1][n-1]==INT_MAX)
            {table[m-1][n-1]=act(src, dst, m-1, n-1);}
        if (table[m-1][n]==INT_MAX)  
            {table[m-1][n]=act(src, dst, m-1, n);}
        if (table[m][n-1]==INT_MAX)  
            {table[m][n-1]=act(src, dst, m, n-1);}
    
        if (src.at(m-1)==dst.at(n-1)) {
            return min(table[m-1][n-1], min(1+table[m-1][n], 1+table[m][n-1]));
        } else{
            return min(table[m-1][n-1]+1, min(1+table[m-1][n], 1+table[m][n-1]));
        }
    
    }

    vector<vector<int>> table;
    int minDistance(string src, string dst) {
            int M=src.length();
            int N=dst.length();
            if (M==0) return N;
            if (N==0) return M;
            table.resize(M+1, vector<int>(N+1, INT_MAX));
            table[0][0]=0;
            int counter=0;
            for (int &n:table[0]) n=counter++;
            for (int m=0; m<M+1; ++m ) table[m][0]=m;
            return act(src, dst, M, N);
    }


3. Extension of problem 2.  If we want every operation path is a valid word in a dictionary?  give the path or if no path through return empty path.

4.Unique Paths
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). How many possible unique paths are there?

Solution: typical DP problem. This number is actually Combine(m-1+n-1, m-1) = (m+n-2)!/ (m-1)!(n-1)!  
Easy?  Yes, but it is hard to avoid overflow  if you just return this one line.  DP is easier comparing to that.  
This gives a hind how to answer the combination problems too,  If the question is C(m,n), I would code in this way.  The equation holds for  C(m,n)= C(m-1,n)+C(m, n-1)
Also C(m,n)= C(m-1, n) (m+n)/m;    C(m,n)= C(m, n-1) (m+n)/n;  

class Solution {
public:
    vector<vector<int>> ct;
    int path(int m, int n, int y, int x){
        if (ct[y][x]) return ct[y][x];
        if (y==m-1 ||x==n-1) return 1; 
        ct[y][x] = path(m,n,y+1,x)+ path(m,n,y,x+1);
        return ct[y][x];
    }    
    int uniquePaths(int m, int n) {
        ct.resize(m, vector<int>(n,0));
        return path(m,n, 0,0);
    }

};



5. Unique Paths II
Follow up for "Unique Paths":   Now consider if some obstacles are added to the grids. How many unique paths would there be?An obstacle and empty space is marked as 1 and 0 respectively in the grid. For example,There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]


The total number of unique paths is 2. Note: m and n will be at most 100.
Solution: My code is messy. Just try to set the boundary parameters. Actually for O complexity vise,  it does not need to set. But it just cannot pass leetecode time limits. So instead of only setting the corner, I have to set two boundary sides.
class Solution {
public:
    vector<vector<int>> ct;
    int m, n;
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        m=obstacleGrid.size();
        n= m==0? 0:obstacleGrid[0].size();
        ct.resize(m, vector<int>(n,-1));
        bool set0=false;
        for (int i=n-1; i>=0; --i){
            if (set0) {ct[m-1][i]=0; continue;}
            if (obstacleGrid[m-1][i]!=1) ct[m-1][i]=1;
            else {ct[m-1][i]=0; set0= true;}
        }
        for (int i=0; i<m; ++i) ct[i][n-1]=0;
        for (int i=m-1; i>=0; --i){
            if (obstacleGrid[i][n-1]!=1) ct[i][n-1]=1;
            else break;
        }
        return path(obstacleGrid, 0,0);
    }
    int path(vector<vector<int>>& obstacleGrid, int y, int x){
        if (obstacleGrid[y][x]==1) return 0;
        if (ct[y][x]!=-1) return ct[y][x];
        ct[y][x] = path(obstacleGrid,y+1,x)+ path(obstacleGrid,y,x+1);
        return ct[y][x];
    }

};


Linear problem and extension, Array, Bucket water, Rain water, Stock sale

Solutions by linear scan. Solve local and propagate linearly. If you cannot transform the problem to local units, things went wrong.

1. Trapping Rain Water   (Leetcode)

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.
For example, Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
Solution Notes:
1) Compare the height of two sides. Work on lower side. 
              If it decreases moving toward middle, then water can hold, but the more decrease hold more,                  so the basin base needs to store to be deducted in future;
2)          If it increases, local units completed.  Calculate local amount by width X sides - base;
              This side is renewed and compared to the other side. We continue working on lower side.
3) Watch the end condition.  I am not sure how to write it optimally. I added a judgement of l+1==r in decreasing case. 


int trap(vector<int>& height) {
        int l=0, r= height.size()-1;
        if (l>=r) return 0;

        int lBase=0, rBase=0;
        int amount=0;
        int lTop=height[l]; 
        int rTop=height[r];
        int l_ind=l, r_ind=r;
        
        while (l<r){
            if (lTop<=rTop){ //move l side
                if (height[++l]<lTop) {
                    lBase+=height[l];
                    if (l+1==r) { 
                        amount+= lTop*(l-l_ind)-lBase;
                        return amount;
                    }
                }
                else {
                    amount+= lTop*(l-l_ind-1)-lBase;
                    lBase=0;
                    lTop=height[l];
                    l_ind=l;
                }
            }else{ //move r side
                if (height[--r]<rTop){
                    rBase+=height[r];  
                    if (l+1==r) { 
                        amount+= rTop*(r_ind-r)-rBase;
                        return amount;
                    }
                } 
                else {
                    amount+= rTop*(r_ind-r-1)-rBase;
                    rBase=0;
                    rTop=height[r];
                    r_ind=r;
                }
            }
        }
        return amount;
    }


2. Container With Most Water

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Solution: Compare all pairs is O(n^2). Taking advantage of the position information can improve it to O(n). 
Note that, first we use two ends to make a widest rectangle. Try to move lower side inward. If the height decrease, the rectangle becomes lower and narrow, just pass. Whenever it grows higher, we can evaluate if this narrower but higher rectangle bigger. 
Note 2, Keep moving the lower side. Otherwise, some local high rectangle could be missed.
Note 3, To write this kind of l<r code, first is to clearly write down the initial condition and decide the variables. Otherwise the code can be messy.

    int maxArea(vector<int>& height) {
        if (height.empty()) return 0;
        int l=0;
        int r=height.size()-1;
        if (r==0) return 0;
        //initilize
        int lTop=l;
        int rTop=r;
        int local=min(height[lTop],height[rTop])*(r-l), global=local;
        
        while (l<r){
            //move left
            if (height[lTop]<=height[rTop]){
                l++;
                if (height[l]<=height[lTop]){  //getting lower and narrower, nothing change
                    continue;
                } else if (height[l]<height[rTop]){ //higher than lTop, but still lower than rTop
                    local= height[l]*(r-l);
                } else { //higher than rTop
                    local= height[rTop]*(r-l);
                    lTop=l;
                }
                global= max(local, global);
            }else{
                r--;
                if (height[r]<=height[rTop]){  //getting lower and narrower, nothing change
                    continue;
                } else if (height[r]<height[lTop]){ //higher than rTop, but still lower than lTop
                    local= height[r]*(r-l);
                } else { //higher than lTop
                    local= height[lTop]*(r-l);
                    rTop=r;
                }
                global= max(local, global);
            }
        }
        return global;
    }




3. Merge interval (leetcode)


Given a collection of intervals, merge all overlapping intervals.

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

    vector<Interval> merge(vector<Interval>& intervals) {
        sort (intervals.begin(), intervals.end(), [](Interval a, Interval b) { return a.start < b.start;});
        int N=intervals.size();
        vector<bool>marker(intervals.size(), true);
        for (int i=0; i<N-1; ++i){
            if (intervals[i].end>=intervals[i+1].start){
                intervals[i+1].start=min(intervals[i].start, intervals[i+1].start);
                intervals[i+1].end=max(intervals[i].end, intervals[i+1].end);
                marker[i]= false;
            }
        }
        vector<Interval> ret;
        for( int i=0; i<N; ++i){
            if (marker[i]){
                ret.push_back(intervals[i]);
            }
        }
        return ret;

    }


4. Look for insert position (leetcode)

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
Solution: binary sort with judgement on m-1 or m+1;
    int searchInsert(vector<int>& nums, int target) {
        if (nums.empty()) return 0;
        int N=nums.size();
        int l=0, h=N-1;
        while(l<=h){
            int m=l+(h-l)/2;
            if (nums[m]==target) return m;
            else if (nums[m]<target){
                if(m+1==N || nums[m+1]>=target) return m+1;
                else l=m+1;
            }else if (m==0 ||nums[m-1]<target) return m;
            else h=m-1;
        }
    }

5. Insert Interval (leetcode)


Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
Solition:   Bugs there, to fix later.

    //binary search 
    int bs(vector<Interval>& intervals, int target){
        int l= 0;
        int r= intervals.size()-1;
        int N= intervals.size();
        while(l<=r){
            int m=l+(r-l)/2;
            if (intervals[m].start==target){
                return m;
            }else if (intervals[m].start<target){
                if (m+1==N || intervals[m+1].start>target) return m+1;
                else l=m+1;
            }else {
                if (m==0 || intervals[m-1].start<target) return m;
                else r=m-1;
            }
        }
    }

    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        int ind_s= bs(intervals, newInterval.start);
        int ind_e= bs(intervals, newInterval.end);
        vector<Interval> ret;
        int N= intervals.size();
        if (intervals.empty()) {
            ret.push_back(newInterval); 
            return ret;
        }

        //no interaction case ,   ind_s =3, ind_e=3  ; including s=e=0 case
        if (ind_s==ind_e) {
            ret= intervals; 
            if (ind_s==0 ) ret.insert(intervals.begin(), newInterval);
            else {
                if (intervals[ind_s].end<=newInterval.end){ //replace ind_s with newInterval
                ret[ind_s]= newInterval;}
                else if (intervals[ind_s-1].end > newInterval.end) { //combine to ind_s
                    ret[ind_s].start= min(ret[ind_s].start,newInterval.start );
                    ret[ind_s].end= max(ret[ind_s].end,newInterval.end );
                }
            } 
            return ret;
        }
        
        int end= max(intervals[ind_e-1].end, newInterval.end);
        int start;
        
        //ind_e >ind_s   at least cross two intervals
        if (ind_s==0) {  //pack from s to e to one bin
            Interval combine(min(intervals[ind_s].start, newInterval.start), end);
            ret.push_back(combine);
            for (int i=ind_e; i<N; ++i){
                ret.push_back(intervals[i]);
            }
        }else{   //s at least 1
            for (int i=0; i<ind_s-1; ++i){
                ret.push_back(intervals[i]);
            }
            
            if (intervals[ind_s-1].end>= newInterval.start) {start=intervals[ind_s-1].start;}
            else {ret.push_back(intervals[ind_s-1]); start= newInterval.start;};
            
            Interval combine(start, end);
            ret.push_back(combine);
            for (int i=ind_e; i<N; ++i){
                ret.push_back(intervals[i]);
            }
        }
        
        return ret;
    }


6. Best Time to Buy and Sell Stock(leetcode)

Say you have an array for which the ith element is the price of a given stock on day i.  If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Solution:  The problem is clear to maintain max profit when the price drops to be lower than old buy. But you have to wait until next drop to conclude local profit. Compare this local profit to the global max profit.   One scan is ok, so it is O(n).
int maxProfit(vector<int>& prices) {
        int profit=0;
        int buy=0, sell=0;
        if (prices.empty()|| prices.size()==1) return 0;
        
        for (int i=1; i<prices.size(); ++i){
            if (prices[i]> prices[buy]) {
                sell= i;
                int profit_local=prices[sell]- prices[buy];
                if (profit_local>profit) profit= profit_local;
                
            } else if (prices[i]<prices[buy]){
                buy= i;  //waiting for end
                sell=  i;
            }
        }
        return profit;
    }

7. Best Time to Buy and Sell Stock II(leetcode)

Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Solution:  The change here is to accumulate all local profit.  The local condition becomes if (prices[i]<=prices[sell])  That is, if only current price is lower than last sell, last sell profit is done and sum in. We buy new at this point.  If current is bigger than last sell,  we just assume we sell it now. (update sell day and profit, who knows tomorrow?)  
    int maxProfit(vector<int>& prices) {
        int sell=0, buy=0, profit_sum=0, profit=0;
        if (prices.size()<2) return 0;
        for (int i=1; i<prices.size(); ++i){
            if (prices[i]>prices[sell]){
                sell=i;
                profit= prices[sell]- prices[buy];
            }else if (prices[i]<=prices[sell]){
                profit_sum+= profit; 
                buy=i; 
                sell=i; 
                profit=0;
            }
        }
        profit_sum+= profit; 
        return profit_sum;

    }


10. Longest Consecutive Sequence


Given an unsorted array of integers, find the length of the longest consecutive elements sequence.For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.  Your algorithm should run in O(n) complexity.
Solution:  I struggle on this problem for long. I wrote a couple of codes but all failed to be O(n).  I thought about set or map. But I tried to count during building up.    This problem becomes so easy if we just delete val+-1  from a set.   
    int longestConsecutive(vector<int>& nums) {
        set<int> ss;
        for (int n:nums) ss.insert(n);
        int maxL=1;
        for (int n:nums){
            if(ss.erase(n)){
                int L=1;
                int val=n;
                while (ss.erase(++val)){}
                L+= val-1-n;
                val=n;
                while (ss.erase(--val)){}
                L+= n-val-1;
                if (L>maxL) maxL=L;
            }
        }
        return maxL;

    }

Thursday, November 5, 2015

Medium Level Tree Problems

1.  Up side down a tree

Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root.
Given a binary tree {1,2,3,4,5},
    1
   / \
  2   3
 / \
4   5
return the root of the binary tree [4,5,2,#,#,3,1].
   4
  / \
 5   2
    / \
   3   1  
The problem is not really hard, but it is confusing enough.
This can be achieved by recursion.  Note:
1)For the left , let it be new root;
2) for the right, let it be the new left.
3) Do not forget to reset root and right's children to NULL. Otherwise, it is infinity loop.


TreeNode* upDown(TreeNode*root){    
    if (!root) return nullptr;
    if (!root->left) return root;

    assert(root->left);
    TreeNode* l= root->left;
    TreeNode* r= root->right;
    TreeNode* newH= upDown(root->left);
    l->right= root;
    l->left= upDown(r);
    root->left=0;
    root->right=0;
    if (r) { r->left=0; r->right=0;}
    return newH;
}

2.Convert Sorted Array to Binary Search Tree   and vise

The problem can be easy if one knows to use the middle element as root. Assign left part to left children and right part to right children.  Then recursion is very easy.
If the initial thought is going to place tree node in order of the array, you will have a painful day.

    TreeNode* sortedArrayToBST(vector<int>& nums, int l, int r){
        if (l>r) return nullptr;
        if (l<=r){
            TreeNode* root= new TreeNode(0);
            int m=(l+r)/2;
            if (l==r) {
                root->val= nums[l];
                return root;
            }
            if (m==l){//two elements
                root->val= nums[l];
                TreeNode* right= new TreeNode(nums[r]);
                root->right=right;
                return root;
            }
            //more than 3 elements
            root->val= nums[m];
            root->left= sortedArrayToBST(nums, l, m-1);
            root->right= sortedArrayToBST(nums, m+1,r);
        }
    } 

    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.empty()) return nullptr;
        return sortedArrayToBST(nums, 0,nums.size()-1);
    }

To convert BST to Array is straight forward an In Order traversal.

3. Find the Kth Smallest nodes in BST

Solution: Think: the 1st smallest is at the left bottom most; 2nd is first parent, 3rd is the sibling of the first.  So it is actually In order traversal.  During traversal, counting down K. When K becomes 0, you get the kth.


void countSmall(TreeNode* root, int& k, int& target){

        if (!root) return;

        countSmall(root->left, k, target);

        if (--k==0){target=root->val; return ;}

        countSmall(root->right,k, target);

    }

    int kthSmallest(TreeNode* root, int k) {

        int target;

        countSmall(root, k, target);

        return target;

    }

4. Maximum path sum in Binary Tree

Given a binary tree, find the maximum path sum.  For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path does not need to go through the root.
Solution: 
1) The first main problem is to divide the problem to Local and Global:
     The path sum uses the local root has ability to grow, so it is global. We have to propagate it not matter how big it is right now. (variable ext in the code)
      The local branch 's current maximum is decided and will not change any more. It will be checked right now to get the combination biggest using both local root, left and right. (variable local in the code)

2) One point needs to be careful. 
    local is obtained by  the biggest among local_left, local_right, ext.  Do not try to connect local_left or _right to root because you never know  how faraway they are.  Since ext is for sure to use root, we compare with ext to determine new local.

    void maxPathSum(TreeNode* root, int& local, int&ext) {

        int localL, localR, extL, extR;
        //leaf
        if (!root->left &&!root->right){
            local= root->val;
            ext= root->val;
            return;
        }
        //both children
        if (root->left &&root->right){
            maxPathSum(root->right,localR, extR);
            maxPathSum(root->left, localL, extL);
            int cross= max(extL+extR+root->val, root->val);
            ext= max(max(extL,extR)+root->val, root->val);
            local= max(cross, max(localL, localR));
            local= max(local, ext);
            return;
        }
        //only left
        if (root->left){
            maxPathSum(root->left, localL, extL);
            ext=max(extL+root->val, root->val); 
            local=max(ext, localL); 
            return;
        }
        //only right
        if (root->right){
            maxPathSum(root->right, localR, extR);
            ext=max(extR+root->val, root->val); 
            local=max(ext, localR); 
            return;
        }        
    }    

    int maxPathSum(TreeNode* root) {
        if (!root) return -INT_MIN;
        int local, ext;
        maxPathSum(root, local, ext);
        return max(local, ext);
    }

I shortened the code by processing the nullptr root. 

The problem is there is no good indicator  for integer value. I used INT_MIN. It has integer overflow problem. So I have to cast to double to make sure when INT_MIN come into calculation. But the code is shorter.

    void maxPathSum(TreeNode* root, int& local, int&ext) {
        if (!root) {local= INT_MIN;  ext=INT_MIN; return; }
        int localL, localR, extL, extR;
        maxPathSum(root->right,localR, extR);
        maxPathSum(root->left, localL, extL);
        int cross= max(double(extL)+extR+root->val, double(root->val));
        ext= max(max(double(extL),double(extR))+root->val, double(root->val));
        local= max(double(cross), max(double(localL), double(localR)));
        local= max(local, ext);
        return;
    }
    
    int maxPathSum(TreeNode* root) {
        int local, ext;
        maxPathSum(root, local, ext);
        return max(local, ext);
    }