Showing posts with label stack. Show all posts
Showing posts with label stack. Show all posts

Tuesday, May 29, 2018

Leetcode 94: Binary Tree Inorder Traversal

May 29, 2018

Introduction


I could not believe that I finally can write working solution using recursive solution today. It is quick and fast. I still remembered that I did choose to write a recursive solution, instead I wrote an iterative solution with some bugs on important meeting. This past 12 months I definitely have done some good training. I CAN write a recursive function very easily on binary tree.

I like to submit as many algorithms as possible on Leetcode.com.

Recursive solution


Here is my recursive solution.

Iterative solution


I like to go over the algorithm with tag stack. I wrote an iterative solution using stack, and it is good workout for me to master stack algorithm one more time.




Thursday, January 18, 2018

Leetcode 84: Largest rectangle in histogram

January 18, 2018


Introduction


It is the hard level algorithm and it can be solved used stack to achieve the optimal time complexity O(N) where N is the array's length. The algorithm is called largest rectangle in histogram.

On January 17, 2018, I had a mock interview and I was asked to work on the algorithm. I went through the brute force solution first, but I did not come out the optimal solution to lower the time complexity to O(N).

One more practice 


What I like to do is to study one blog I like in June 2015, and then rewrite the notes and also write the C# code as well. It is very easy to look up past practice, here is my blog to document the practice in June 2015. At that time, I was shy and did not write down my thinking process to learn to solve the problem.

Right now, I think that it is very important to write down thinking process and also the idea to break through the hurdles in the problem solving. I think that it is more important to build up some new habit to learn to solve a problem. Write down the constraints, write down the problem, difficult issues, concerns, and then ideas to solve the problem, or ideas to solve partial solution. 

First, I rewrote the note to make it more readable, and then saved a gist. Here is the gist. 


Analysis of the algorithm



Most of important is to write down the analysis, and that is something lasting longer than coding itself. Specially if I draw something to highlight the main design ideas and it will be extremely helpful to bring back the memory.

This time I drew one to help myself learn the design using stack, check upward and downward.


The main idea is very simple to explain in Chinese, let us take a look at notes in Chinese first, and then I quickly explain them in English.


Going upward



When the graph is going upward, in detail, current index is i, next step is i + 1, and height[i] < height[i + 1], there is no need to calculate the area. Since it is getting bigger value when i moves to next value.

Going downward



When the graph is going downward, in detail, current index is i, next step is i + 1, and height[i] > height[i + 1]. it is time to calculate the current rectangle's area.

Get help from a stack 


At the current index i, only right end's index is known, how to get the left end's index? So in order to iterate the array, a stack is need to maintain the backtracking history.

How to design a stack?


In this stack the right end's index is saved to the stack, but when is time to push into stack? Every time there is element in the array which is bigger than the top of the stack, push the index to the stack. Otherwise it is time to calculate the current rectangle's area and compare to the largest area.

Every algorithm will become one of your valuable weapons 
until you teach some one and show him/ her how it work.

Tuesday, May 31, 2016

Leetcode 103: Binary Tree ZigZag traversal - a practice

May 31, 2016

Review the blog:
http://juliachencoding.blogspot.ca/2015/06/leetcode-zigzag-order-traversal-of.html

practice in 2015:
https://github.com/jianminchen/zigzagOrderTraversal/blob/master/Program.cs

Warmup practice on May 31, 2016, write a C# solution again:
https://gist.github.com/jianminchen/3723020cd9757f85d0ceb383da425c6c

Practice notes:

1. source code line 107 ,  Stack, use ref, pass reference.

Lookup why Stack is different from Array. Array reference is passed automatically.

Read the blog:
http://stackoverflow.com/questions/967402/are-arrays-or-lists-passed-by-default-by-reference-in-c

2. Extract a function named swap(), actually, the last practice:
https://github.com/jianminchen/zigzagOrderTraversal/blob/master/Program.cs

line 57, Stack<int> tmp is declared, but line 92 tmp is used. The scope is too large to pay attention. So, extract it to a function.

3. The last practice first while loop on line 59:
https://github.com/jianminchen/zigzagOrderTraversal/blob/master/Program.cs

It is confusing, so in current practice, line 72, while(true),
line 72: while(true)

later, on line 112, break the while loop.
line 112: if (currLevel == null || currLevel.Count == 0)
113: break;

4. line 61, if (root == null), return empty list instead of null pointer.

Nov. 14, 2016
Google/Bing Search Result:
zig-zag traversal of a binary tree in c

Review the blog, and then, need to document about array reference passing in C#, see stackoverflow article:
http://stackoverflow.com/questions/12757841/are-arrays-passed-by-value-or-passed-by-reference-in-java




Thursday, May 26, 2016

HackerRank: string algorithm - Reverse Shuffle Merge - Stack, backtracking techniques

May 26, 2016

Reverse Shuffle Merge - Problem statement:

Algorithm analysis:
Use test case: "abcacb" to explain the solution: 
int[] add = new int[26], 
int[] skip = new int[26]
a - 0, b - 1, c -2 
add[0] = 1, add[1] = 1, add[2] = 1, 
skip[0] = 1, skip[1] = 1, skip[1] =1, 

Find smallest lexical string. 

reverse input char one by one:
push b into stack, 
'c' > ''b', then, push c into stack
stack:
c
b
Now, a is scanned, 'a' < stack.peek() = 'c', skip[2] = 1 > 0, 
backtracking, pop c out of stack, skip[2] = 0
Now, 'a' < stack.peek() = 'b', skip[1] = 1 > 0, 
backtracking, pop b out of stack, then adjust skip[1] = 0
add[0] >  0, push a into stack, add[0] = 0, 
next, c is scanned, cannot skip, push into stack, 
next, b is scanned, cannot skip, push into stack, 
next, a is scanned, skip a. 
stack.ToArray(), keep stack iterator order, "bca", 
Array.Reverse(stack.ToArray()) -> "acb"
Lexical smallest string. 


previous blog: 

warmup practice:

Second practice:
so many bugs in second practice:
1. confused on skip, add array --, ++; line 71, line 80 did the opposite.
2. string reverse, char[], string, Array.Reverse etc. lookup
3. add one more test case: "abcacb",
    b in stack, c in stack, then, run into a, pop up c, and pop up b, let 'a' in the stack. Two in row pop up in stack. While loop is tested on line 64 - 67.
4. while statement from line 64 - 67, fix compile error.
   both are ok to compile:
(char)stack.Peek() > runner)
(char)stack.Peek() - runner > 0)

Third practice:
The code passes HackerRank online test cases as well.

A few good changes:
1. add comment from line 67 - line 72, test case: "abcacb", 
use test case, stack top -'c' is removed, help to ensure the code is correct.
2. line 73, avoid bug to overwrite the variable runner, create a new variable called backTracked.

https://gist.github.com/jianminchen/8e2c28262dd3d13c4db856feaed5603e

Fourth practice:

1. create a new function getIndex - on line 100 - 103
2. after reading through the code, still missed a bug in writing - on line 55; debug the code and find
the result of first test case "abcacb" should be "acb", but it was "bca".

Julia examined line by line, but still missed the bug on line 55.

https://gist.github.com/jianminchen/7572e92ea48211d3d05c557d97601dbf

Read C# string constructor char[]: spend 10 - 20 minutes to read all constructors of string in C#.
https://msdn.microsoft.com/en-us/library/aa331865(v=vs.71).aspx


Wednesday, May 25, 2016

Binary Tree Preorder Traversal - Iterative Solution - Warm up Practice

May 25, 2016

Review blogs - Leetcode binary tree preorder traversal

C# practice:

use stack, and also know the order to push child nodes: right child first, and then left child next.

Code is here.

Question and Answer:
1. How is the practice?

Julia first thought about using queue to implement the solution, left child first, and then right child next. But, it does not work, since left child's left child should go to traversal first before right child. So, she had to stop.

Then, she tried to look into iterative solutions in general through Google, and also checked her previous practice.

Next time, go through a test case, do some analysis on the test case. Draw some diagram, help yourself to analyze, at least behaves like a teacher.

2. Things to work on through the practice?
queue -> stack -> opposite order to push into stack

3. Can you describe the process using your own words, a few of drawings to help the thinking process?

First, read the wiki article about stack.

Let us work on a simple test case:
The preorder traversal of tree: 1 2 3 4 5 6 7
When the root node 1 is visited, 2 and 5 should be added to some data structure, 3 and 4 will be added after 5, but output of 3 and 4 should be before 5.
In other words, the data structure should accommodate last in first out feature. So, it is stack!
Once stack is chosen to use, then work out the simple tree first with 3 nodes:

preorder traversal: 1 2 5
so, push 1 into stack, and then, pop out. 5 is pushed in stack first, and then it is turn of 2.

Next, work on the test case: tree - preorder traversal 1 2 3 4 5 6 7
1 is pushed into stack,
1 is on the top of stack, 1 is popped out,

1's right child 5 is pushed into stack,
1's left  child 2 is pushed into stack,

2 is popped out from stack,

2's  right child 4 is pushed into stack,
2's  left  child 3 is pushed into stack,

3 is popped out from stack,
4 is popped out from stack,

5 is popped out from stack,

5's right child 7 is pushed into stack,
5's left  child 6 is pushed into stack.

6 is popped out from stack,
7 is popped out from stack.

3. Most favorite problem solving using stack?

HackerRank: string algorithm - Reverse Shuffle Merge (IV)



warmup practice - C# practice code

Second practice:

C# code

so many bugs in second practice:
1. confused on skip, add array --, ++; line 71, line 80 did the opposite.
2. string reverse, char[], string, Array.Reverse etc. lookup
3. add one more test case: "abcacb",
    b in stack, c in stack, then, run into a, pop up c, and pop up b, let 'a' in the stack. Two in row pop up in stack. While loop is tested on line 64 - 67.
4. while statement from line 64 - 67, fix compile error.
   both are ok to compile:

(char)stack.Peek() > runner)
(char)stack.Peek() - runner > 0)

Third practice:

The code passes HackerRank online test cases as well.

A few good changes:
1. add comment from line 67 - line 72, test case: "abcacb",
use test case, stack top -'c' is removed, help to ensure the code is correct.
2. line 73, avoid bug to overwrite the variable runner, create a new variable called backTracked.

C# practice

August 8, 2016

Work on facebook code lab, preorder iterative solution. Chicken out! Forget to enforce the rule, right child goes to stack first, and then, left child goes to stack afterwards. And then, instead, nervousness kicked in, gave up in 5 minutes, looked up blogs.

Need more practice!

3 smart choices to ask myself: 

stack vs queue ->
left, right who goes first ->
enforce rule, null pointer will not go into stack, save time ->

one node ->
3 node tree - complete binary tree ->
7 node tree - complete binary tree

Wednesday, May 11, 2016

HackerRank – Connected Cell in a Grid - Warm up with Five Practices (V)

May 11, 2016


Being a software programmer, it is easy to spend hours to read and catch up technologies, work on new algorithm, but no coding, one day, or one week, even half month/ month. 

So, warm up like sports. Julia chose the algorithm - Connected Cell In a Grid to warm up for a few hours. 

Last time, less than 1 month ago, Julia did work on this algorithm – connected cell in a grid. And then, she started to warm up again.

Here is one of blogs last practice on April 16, 2016:

Fifth practice, using stack instead of recursive function, implement the DFS algorithm:

Question and Answer:

1. What do you like the approach - using stack, DFS algorithm? 

To write using stack is similar to using queue, but the search is DFS instead of BFS. Julia does not have time to build a test case to compare the order of visited nodes this time. 

HackerRank – Connected Cell in a Grid - Warm up with Five Practices

May 11, 2016

Being a software programmer, it is easy to spend hours to read and catch up technologies, work on new algorithm, but no coding, one day, or one week, even half month/ month. 

So, warm up like sports. Julia chose the algorithm - Connected Cell In a Grid to warm up for a few hours. 

Last time, less than 1 month ago, Julia did work on this algorithm – connected cell in a grid. And then, she started to warm up again.

Here is one of blogs last practice on April 16, 2016.

First practice, it takes her close to 60 minutes to write, fix issues.  Use dimensional array, use queue to do BFS – breadth first search.


Here are mistakes:
      1. Forget to add boundary check function, do boundary check (source code: line 108)

      2. Forget to introduce neighbor_X, neighbor_Y  (source code: line 90, 91)

      3. Neighbor_X is mistakenly written as neighbor_Y, so wrong answer;
          Debug the code and find the issue. It takes more than 20 minutes, a lot of stress. (source code: line 96)

So, it is excellent chance to learn and improve the performance.

Write a small function to debug the code, figure out the wrong answer issue – testRoutine, source code: line 36.


Second practice, using queue, but use jagged array:  (20 minutes to write)

          

Third practice, use DFS – recursive function, which also returns the count.

         

Fourth practice, using DFS – recursive function, but use an argument – reference int to track value


Fifth practice, using stack instead of recursive function, implement the DFS algorithm:



Question and answer:

      1. What do you learn through the warm up? Do you learn some better ways to fix the bugs?
It is better to write down the functions needed to help the task, this way, you will be more efficient.

Here are 4 tasks:
     1. Calculate the key
     2. Boundary check 
     3. Maximum value search
     4. Using queue to do search

     2.  Why do you do warm up this time? What are the advantages?

Julia still remembers the favorite tip to work on the tasks:
1.    Just mark the visited node as 0 from value 1
2.    Update node value from 1 to 0 before it is added to the queue
3.    Use key = row * 10 + col, since row < 10, col < 10 to track each node in the queue

Julia likes to write code and do some warm up, therefore, she can get more experience; she tries to improve performance to 20 minutes for this kind of DFS, BFS, matrix, search algorithm.

3. Do you reproduce the experience of high stress to trouble shooting and work on bug fix? 

Julia reproduced the issue of high stress, she could not fix the bug on her first practice. So, she wrote a small debug function try to figure out; actually, it is a mistake in writing. 

Next time, reexamine every line of code, every variable, every executable path, when the code is executed. Do not depend on debugging, running the code, because stress level is high. 

Saturday, April 2, 2016

HackerRank: string algorithm - Reverse Shuffle Merge (II) - next - forming a partial correct idea

April 2, 2016

  Problem statement is here.   

  Introduction


Julia likes to share her experience, advance level on HackerRank. It is not bad in the weekend, spend 2 hours messing around the ideas/ hackerRank, come out a clear greedy algorithm. The hackerRank definitely helps Julia to shape her idea from start to end.

Practice talk 


  First two hours work - failed twice, detail here in the blog.     

  Here is the idea after 2 hours intensive work:
of course, "abc" is the smallest one in lexicographical order, but the possible string formats:
  *a*b*c*, not *abc*, now * means any number of any chars.

 Let us count how many of a, b, c can be skipped when we do linear scan of a string.

 Now, it should be very easily to introduce greedy algorithm.

 For example, if linear scan from left to right, visiting char b, then, we have to check how many b's left can be skipped, if it is bigger than 0, we have to check any char before b has anything left or not. For example, if a still has some number left to skip; we hold on b, just skip current b.

 Otherwise, count current b into the string we are looking for, and decrease the number count of b (recording how many b can be skipped).

Use an example to explain:
  a2b2c2 case,
 ba*, the half should be a1b1c1,
 so, skip first char 'b', since greedy algorithm / let 'a' go first.

 Give it a try, implement the idea:

 Some statistics: advanced algorithm 4+ hours - A mountain - "Sea to sky Gondola" to climb

Spent 9:47 am - 11:47 am, wrote code, but still failed most of case; only pass "eggegg";
Hard to concentrate, and think about the issue - this reverse is tricky!

Here is the C# solution - 3 rd failed try. Code is here.

Baby hacker is crying, still score zero: 4 hours work. Code is here.

Now, it is 1:47 pm, another 2 hours with music, the code was submitted, now score 16.67/ 50. Still need to work on more before Julia plan to read other people's solution:

Some statistics: advanced algorithm 6+ hours - A mountain - Sea to sky Gondola to climb. Code is here. 

Need to stop, go to enjoy outdoor activities!

Baby hacker is showing off her baby steps, the report of test cases pass/ fail on Hackerrank is here.

Try to fix the error, give up - the design has another flaw,
test case:
djjcddjggbiigjhfghehhbgdigjicafgjcehhfgifadihiajgciagicdahcbajjbhifjiaajigdgdfhdiijjgaiejgegbbiigida
i=50, s[i] = 'g', the design let 'g' skip, but
i=52, s[i] = 'i', 'i' has to be added to the output, no more skip.

<-  Julia, think about stack, use some data structure to do reverse work <- such a great workout! Release all my stress and headache, and be humble!

5:12 pm, statistics: Another 3 hours, total: 9+ hours 

Follow up 


May 3, 2017

Monday, February 8, 2016

Leetcode 329: Longest increasing path in matrix

February 8, 2016

problem statement:
Given an integer matrix, find the length of the longest increasing path.From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).
329. Longest Increasing Path in a matrix


Example 1:
nums = [
  [9,9,4],
  [6,6,8],
  [2,1,1]
]
Return 4
The longest increasing path is [1, 2, 6, 9].
Example 2:
nums = [
  [3,4,5],
  [3,2,6],
  [2,2,1]
]
Return 4
The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.
idea: go through each node in the matrix, BFS search, and get minimum one;

read blog:
http://bookshadow.com/weblog/2016/01/20/leetcode-longest-increasing-path-matrix/

Wednesday, February 3, 2016

Algorithm: reading blog

February 2, 2016

 Think about learning Python today, since Julia likes to read Python code and get some great ideas in the code. She starts to read the blogs from Leetcode question 331 to 1 in descending order.

  As a programmer, she spent over 6 months to learn Javascript in 2014, and then she loves to read Javascript code now. So, spend 10 - 20 minutes a day to learn Python, one day she will love to read Python code.

  Here is the blog she starts to read.

  http://bookshadow.com/leetcode/

  https://www.hrwhisper.me/leetcode-algorithm-solution/

  http://www.cnblogs.com/grandyang/p/4606334.html

  http://www.cnblogs.com/EdwardLiu/tag/Leetcode/

  http://www.jiuzhang.com/problem/

 Here is the log of her reading:

 Feb. 3, 2016
Leetcode: 331, 330, 329, 328, 327, 326

331. Verify Preorder serialization of a Binary Tree
idea: Use stack

330. Patching Array
Read the blog, understand the idea:
https://leetcode.com/discuss/82822/solution-explanation

329. Longest Increasing Path in a matrix
idea: go through each node in the matrix, BFS search, and get minimum one;

328. Odd Even Linked List (Easy)
Julia's comment: think about O(N) space solution first (using array, and then, easy to go through), and then, work on O(1) space solution, the following blog helps:
http://www.cnblogs.com/EdwardLiu/p/5138199.html

Feb. 4, 2016
327 Count of Range Sum
Still confused about the question, the example is also hard to understand.

324. Wiggle Sort II
Julia figured out the easy way to do it, O(n) time, O(1) space. So motivated. Next time, think about algorithm by yourself, start from brute force, and then, work towards requirement - efficient solution.

https://segmentfault.com/a/1190000003783283
public class Solution { public void wiggleSort(int[] nums) { for(int i = 1; i < nums.length; i++){ // 需要交换的情况:奇数时nums[i] < nums[i - 1]或偶数时nums[i] > nums[i - 1] if((i % 2 == 1 && nums[i] < nums[i-1]) || (i % 2 == 0 && nums[i] > nums[i-1])){ int tmp = nums[i-1]; nums[i-1] = nums[i]; nums[i] = tmp; } } } }

322 Coin change
http://www.cnblogs.com/grandyang/p/5138186.html

这道题只让我们求出最小的那种,对于求极值问题,我们还是主要考虑动态规划Dynamic Programming来做,我们维护一个一维动态数组dp,其中dp[i]表示钱数为i时的最小硬币数的找零,递推式为:
dp[i] = min(dp[i], dp[i - coins[j]] + 1);
其中coins[j]为第j个硬币,而i - coins[j]为钱数i减去其中一个硬币的值,剩余的钱数在dp数组中找到值,然后加1和当前dp数组中的值做比较,取较小的那个更新dp数组

321. Find Maximum number 
https://www.hrwhisper.me/leetcode-create-maximum-number/

319 Bulb Switch 
http://www.cnblogs.com/grandyang/p/5100098.html

Analysis from the above blog:
那么我们来看这道题吧,还是先枚举个小例子来分析下,比如只有5个灯泡的情况,'X'表示亮,‘√’表示灭,如下所示:
初始状态:    X    X    X    X    X
第一次:      √    √    √    √    √
第二次:      √     X    √    X    √
第三次:      √     X    X    X    √
第四次:      √     X    X    √    √
第五次:      √     X    X    √    X
那么最后我们发现五次遍历后,只有1号和4号锁是亮的,而且很巧的是它们都是平方数,是巧合吗,还是其中有什么玄机。我们仔细想想,对于第n个灯泡,只有当次数是n的因子的之后,才能改变灯泡的状态,即n能被当前次数整除,比如当n为36时,它的因数有(1,36), (2,18), (3,12), (4,9), (6,6), 可以看到前四个括号里成对出现的因数各不相同,括号中前面的数改变了灯泡状态,后面的数又变回去了,等于锁的状态没有发生变化,只有最后那个(6,6),在次数6的时候改变了一次状态,没有对应其它的状态能将其变回去了,所以锁就一直是打开状态的。所以所有平方数都有这么一个相等的因数对,即所有平方数的灯泡都将会是打开的状态。
那么问题就简化为了求1到n之间完全平方数的个数,我们可以用force brute来比较从1开始的完全平方数和n的大小

February 7, 2-16
Please understand the question, if the problem is too complex, then the understanding may not be not correct. 

Leetcode 318: Maximum Product of Word Length 
Given a string array words, find the maximum value of length(word[i]) * length(word[j])where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.
https://www.hrwhisper.me/leetcode-maximum-product-of-word-lengths/

Solution 1:
直接看看每个字符串都包括了哪个字符,然后一一枚举是否有交集:
  • 有交集,则乘积为0
  • 无交集,乘积为 words[i].length() * words[j].length()
Solution 2:
其实因为全部都是小写的字母,用int 就可以存储每一位的信息。这就是位运算
  • elements[i] |= 1 << (words[i][j] – ‘a’);   //把words[i][j] 在26字母中的出现的次序变为1
  •  elements[i] & elements[j]    // 判断是否有交集只需要两个数 按位 与 (AND)运算即可
read the blog to understand bit operation, take some time to refresh the memory:
http://www.cnblogs.com/onlyac/p/5155881.html


在一个字符串组成的数组words中,找出max{Length(words[i]) * Length(words[j]) },其中words[i]和words[j]中没有相同的字母,在这里字符串由小写字母a-z组成的。
对于这道题目我们统计下words[i]的小写字母a-z是否存在,然后枚举words[i]和words[j],找出max{Length(words[i]) * Length(words[j]) }。

小写字母a-z是26位,一般统计是否存在我们要申请一个bool flg[26]这样的数组,但是我们在这里用int代替,int是32位可以替代flg数组,用 与(&),或(1),以及向左移位(<<)就能完成。如“abcd” 的int值为 0000 0000 0000 0000 0000 0000 0000 1111,“wxyz” 的int值为 1111 0000 0000 0000 0000 0000 0000 0000,这样两个进行与(&)得到0, 如果有相同的字母则不是0。


Wednesday, January 20, 2016

Leetcode questions 20: Valid Parentheses

January 20, 2016 

Leetcode 20: Valid parentheses


Julia’s C# code:

January 20, 2016

favorite blogs to read: January 20, 2016

Great time to go over different ideas to implement the algorithm, using Map in C++, Hashmap, and see so many talents through those code - 






http://www.jiuzhang.com/solutions/valid-parentheses/

So, ready to review more about parentheses:

Leetcode 32: longest valid parentheses -

Julia’s blog on this question:
Leetcode question 22: Generate Parentheses
https://github.com/jianminchen/Leetcode_C-/blob/master/GenerateParentheses_No22.cs