Showing posts with label tree. Show all posts
Showing posts with label tree. Show all posts

Monday, May 16, 2016

Connect nodes at the same level in a binary tree

May 16, 2016 

Connect nodes at the same level in a binary tree  
http://www.geeksforgeeks.org/connect-nodes-at-same-level/   (? bug)

better one:
http://javabypatel.blogspot.ca/2015/08/connect-nodes-at-same-level-in-binary-tree-using-constant-extra-space.html

Using Queue - 
http://javabypatel.blogspot.ca/2015/08/connect-nodes-at-same-level-in-binary-tree.html

Question and answer:

1. How long do you study the problem? What do you learn? 

Julia spent more than 1 hour to study the blogs above. She will write down her own notes about the test case, analysis and solution, and post them in the blog. Encourage herself to write, to share and to improve her confidence on problem solving. 

Will come back soon. 

Wednesday, January 6, 2016

Divide and Conquer: Preorder traversal of ternary tree


January 6, 2016
重温一道关于树遍历的题目, 在新年开始的第一个星期, 鼓励自己, 加油! 多写代码, 多练习.

Be humble, learn from her mistakes in 2015. Julia is learning how to solve "divide and conquer" - write a perfect recursive function - without bug in base case - recursive calls. 

Her lessons for recursive function design, divide and conquer solution in 2014, 2015:

1. Do the work for root node, but do not do the work for its children; In other words, a subproblem can be handled by a recursive call

2. Do not repeat base case 'if' clause - a checking afterwards in the recursive function call. Not necessary, except trying to use less stack. 

Julia, recursive function design is like dealing with a family - single parent with children; show the work how to handle root node, that is almost done. Let recursive function to take care of children, do not do the work for children nodes. For example, binary tree, 2 children, call recursive function twice; Ternary tree, 3 children, and then, use 3 recursive calls. 

Once again, "Do not do the work for children directly". 

Action items:
1. Work on Leetcode questions again and start with simple questions.

Binary Tree Preorder traversal of ternary tree
More reading about ternary tree:
  https://en.wikipedia.org/wiki/Ternary_search_tree

Tuesday, September 22, 2015

Leetcode 109: convert sorted list to a binary search tree

Sept. 22, 2015

109 Convert sorted list to binary search tree (No. 109)

8/25/2015
Read the following blogs:

C#, bottom up, time O(n), space O(log n) solution - best solution:

C#, top down, time O(n^2), space O(long n) solution - naive solution:

worked on code 2 times, first time, the calculation is kind of messy, then, worked on Leetcode question 108, get the idea to make it more simple; tips like len/2 only shows once, afterwards, use m instead. Just need to improve coding, think to make it more abstract, simple.


9/21/2015
Review the best solution, and then, totally forgot the bottom up solution idea. So, update the code with more comment.

Need to review more about bottom up/ top down solution in tree problems. Get more experience on bottom-up solution, read some articles about it. 

9/22/2015

Go over one example to build some muscle memory about this bottom up, O(1) solution to find the root node in subtree function.

Sorted List:
1->2->3->4->5->6->7,

How to convert the above sorted list to a binary search tree?
Thought process:
1.      First, get length of the list, which is 7 in the above list;
2.      Secondly, define a recursive function called
constructBST(ref  TreeNode head, int start, int end)
the above function definition, 3 arguments:
1.      First one is the reference of head node of sorted list,
2.      Start index of the list,
3.    End index of the list

In the function, first define the base case:
head is null, or start<end, return null
start==end, return head

then, call the recursive function for left subtree:
 head node is the same, start is the same, but end is len/2-1;
great tip comes in, the head node should move in the function, so that
root node can be accessed in the list using O(1), instead of starting from very beginning.
One more statement:
head = head.next;
TreeNode root = head;   // return this node as tree root node
Root.left = left subtree root node
Root.right = right subtree recursive function
       constructBST(ref  head.next, mid+1, end)

The tips to remember in the design, the recursive function should return the root node of the tree; secondly, input argument of linked list should use reference, and also head node moves in the recursive function, so it is O(1) to find the root node. 

Just cannot believe that only call .next function once in the recursive function! How to argue that the move is only once? Therefore, the total calls of .next should be length of list. Total recursive function calls is n, length of list. 

Debate why the recursive function has to return root node, and set up root node, connect its left/ right subtree root node. 

Debate why the linked list head node is moving. 

设计这个递归函数, 如何避免从链的头开始访问, 到中间点? 最关键是让链的头移动, 当需要设计树的根节点, 只要移动一步, 就是根节点. 画一个图, 帮助自己理解记忆; 看一篇文章, 开拓思路






The main point to understand the best solution using O(ln N) space, the left subtree has to be built first, and then, head node can be retrieved as .next method call, root node can be set up, and then, left subtree can be built. So, left subtree, then right subtree, then the tree with root node. Bottom up. 

Whereas sorted array to BST, the root node can be find right away, and then, tree can be set up top down. Julia is still confusing this top down / bottom up difference. :-) read more blogs. 

Blogs:
1. use global variable to remember the head node of linked list, great idea:

2. another implementation using two pointers. Try it using C# later. 

3. Java implementation, teach me how to use reference in Java or wrapper class. Good point!

4. Time and space complexity analysis - think about it - very clear analysis 

5. Three implementation discussions 

6. Great explanation - bottom up / top down, and in order traversal/ post order traversal

Implement the above 6 blogs using C#, and then, share the blog. After 1 month, check again and see if I can come out the bottom up solution in 5 minutes. If yes, stop; otherwise review again. 

Dec. 24, 2015
Review the solution again. 
How to recall the solution step by step?

1. Get list length <- travel the list once 

2. Design the recursive function with a list, start and end two position; use the position of start/end to boundary case checking; also the function returns the root node of the tree. 

3. Build left subtree

4. Find the middle of list as root <- how to get there? 
Cannot traverse the list again to half length if you want optimized solution, since it is in recursive function,  O(nlogn)

Every recursive call the list pointer will traverse once

5. Connect root node to left child

6. Move list pointer to next one 

7. Build right subtree
connect root node to right child as well. 

Recap the importance of function design: 
1. list with a pointer moving, starting from head
2. start, end position of linked list 
3. in the function build a tree
4. return root node of the tree

Sunday, September 13, 2015

Leetcode 106: construct binary tree from inorder and post order traversal

Sept. 13, 2015

 Spent more than a few hours to work on the leetcode problem, and my favorite blogs about this problems:

 1. http://siddontang.gitbooks.io/leetcode-solution/content/tree/construct_binary_tree.html

 2. http://blog.csdn.net/linhuanmars/article/details/24390157

 After reading the above reference 1, Julia spent first few hours to write the C# implementation:

 https://github.com/jianminchen/Leetcode_C-/blob/master/106ConstructuBTreeFromInorderPostOrderTraversal.cs

  In her coding practice of function build(...), she spent over 20 minutes to figure out the coding task: the code to partition the inorder traversal into two partitions, first is left subtree, second is right subtree. And then, post order traversal also can be partitioned into two intervals, first one is for left subtree, and then, second one is for right subtree.

  She took more than 10-15 minutes to understand the solution. That is too long for real problem solving. Figure out that only job is to find the root node, and then, its left child and right child is also the root node of left subtree/ or right subtree. The recursive call, actually two of them, can help to do the task.

  So, she needs to cut down the practice time, and make sure the calculation is correct, easy to tell/ maintainable code/ testable code. So, she decided to practice it using class Range instead of two arguements start/ end integers. Hopefully, this practice will enhance her memory about partition the array into two parts, one is dividing in mid point, another one is by length of first interval - left subtree.

public class Range{
public int start, end;
...

}

  Also, she likes to enhance her memory about this solution, so, she writes second implementation using C#, and see if the code can pass online judge. Most important, she tried to use different solution, to improve, challenge herself. Write the code without any mistake first time, in less than 10 minutes based on previous one.

 https://github.com/jianminchen/Leetcode_C-/blob/master/106ConstructBTreeFromInOrderPostOrderTraversal_B.cs

  Julia likes to train herself using leetcode questions, and biggest problem is to cut down the time to write a solution. She tries to cut down time from hours to 10-30 minutes.

  After the code writing, she thought about more about great ideas out there, she should not miss. So, she reads the second reference, and like the most about the analysis:
"这道题和Construct Binary Tree from Preorder and Inorder Traversal是树中难度比较大的题目了,有朋友可能会想根据先序遍历和后序遍历能不能重新构造出树来,答案是否定的。只有中序便利可以根据根的位置切开左右子树,其他两种遍历都不能做到,其实先序遍历和后序遍历是不能唯一确定一棵树的,会有歧义发生,也就是两棵不同的树可以有相同的先序遍历和后序遍历,有兴趣的朋友可以试试举出这种例子."

  Julia 发现在训练自己做题是, 如果能摸索出方法, 提高写代码的速度, 从几个小时, 到10-30 分钟, 那就是很成功的训练. 一种方式, 就是, 找到她喜欢的题解, 能够理解算法; 接下来, 看如何提高写代码的速度, 最好的方式, 就是多写几个解法, 看哪个不容易出错. 

 最后, 就是, 快速看十几个博客, 看有没有错过最重要, 最关键的分析. 

 接下来, 就是重复训练; 分析超时的原因, 能不能达到目的10-15分钟写出正确的代码. 就像网球训练, 训练自己. 



Sunday, September 6, 2015

Morris post order traversal algorithm

Sept. 5, 2015

时间把代码读明白, 比光看书强动手写代码, 改代,  
兴趣是最好的老师. 多记几个例子, 增加情趣. 

举个例子关于中序遍历
           4
        /     \
       2       6
     /  \     / \
    1   3   5   7 
easy way to travel is to remember the order of its position in the horizontal way 

       



现在, 要做Morris 的后序遍, 有一个技巧, 是在我写完这个C#码才发现的, 

                     
                  9
                /    \
               5      8
              / \       \
             1   4     7
                  / \   /
                2   3 6
就是从最左边开始, 历五次

 1, 
 2, 
 3, 4, 5 
 6, 
 7, 8, 9, 


最后结果是 1 2 3 4 5 6 7 8 9 
加一个dummy node, with left child is the root node.