Saturday, June 22, 2019

39. Combination sum

39. Combination sum - a year ago, two year ago two submissions. 

I wrote a post to share on June 22, 2019 based on practice in 2018. Here is the link.


It is time for me to review backtracking algorithm on June 22, 2019. Here is the article I like to review written by a Google engineer. I like to review all algorithms in the article, and I like to share my practice in 2018.
Most important is to avoid timeout issue, one way is to avoid copy the list for each depth first search. If backtracking is used, then only one list is needed for all the searches. Shared space is more efficient, and easy to backtracking as well.
Case study to understand backtracking
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
First, sort the array with all numbers, [2, 3, 6, 7], no duplicate.
Base case, target = 0, empty set.
Remember that we only allow to use one list to store all numbers selected for the target; We will maintain the order of numbers using data structure List, and also add last and pop last for backtracking as well.
Let us start from index = 0, first number is 2, and then 2 is added to the list, continue to search, DFS next step, target is 7 - 2= 5, what is start index for next step?
Work on next index in the design
start index should be index + 1= 1, or index? This is most challenging problem.
One of answers is [2, 2, 7], in other words, next element should start from all possible numbers not less than current number. 2 can be selected more than once consecutively.
In other words, next step is to search from index = 0 again for target = 5, choose 2, put 2 into list, so the list is [2, 2], target = 3, then search next step, [2, 2, 2], target = 1, we could not find any number less than 1, so backtrack, pop last 2 out from list, and then search next step index = 1, value = 3, [2, 2, 3], base case target = 3 is meet, the list is added to final result.

Step by step DFS
[2,2,3], target 7
Base case:
{} empty set -> empty list
List
[2, 3, 6, 7]
Four options to start with, first one is 2,
start with 2,
[2] -> target 5, index start = 0, next step start index still 0
[2, 2] -> target 3, index start = 0,
[2, 2, 2] -> target 1, index start = 0, value: 2 > target: 1, backtrack
[2,2, 3], try next target 0, find the first combination.
[2, 3] -> target 2, index start = 1,
[2, 3, 3] -> value > 8, backtrack
...
My idea of reviewing the solution is to go over the basic DFS steps, and I can explain it clearly like mock interview. The code should be easily to be reviewed.
The above step by step explanation will be reviewed and make it more readable and clearly. I will think about drawing some diagram to help if need.
C# API - how to remove List last item
Here is the idea by looking up stackoverflow.com
List.RemoveAt(rows.Count - 1)
Here are highlights:
  1. Apply depth first search; sort the array in ascending order to help avoid duplicate constraint, since [2, 2, 3] should be same as [2, 3, 2], the order is not important;
  2. Understand that one number can be used multiple times in the combination, so DFS next step start index should be the same as the current one, therefore same number can be selected more than once.
  3. Backtracking is important technique, it is DFS, so the list will be expanded to meet the target or bigger than target or exhaust all possible numbers, and then backtrack, pop last one to allow all options are exhausted.
Time complexity analysis
Each DFS step search at most have n options, n is size of the array. So at most there are target (T) steps in DFS search, so time complexity is O(n^T).
At the beginning, if I decide to analyze time complexity, then I will have a good idea how to solve the problem.

public class Solution {
    public IList<IList<int>> CombinationSum(int[] candidates, int target)
        {
            var result = new List<IList<int>>();
            var combination = new List<int>();
            Array.Sort(candidates);

            CombinationSum(result, candidates, combination, target, 0);
            return result;
        }

        /// <summary>
        /// I like to talk about the design:
        /// this algorithm is like brute force solution, using back tracking. 
        /// combination can be bruted force to find solution. Like minimum value in the combination. 
        /// starting from each one. 
        /// </summary>
        /// <param name="result"></param>
        /// <param name="candidates"></param>
        /// <param name="combination"></param>
        /// <param name="target"></param>
        /// <param name="start"></param>
        private static void CombinationSum(
            IList<IList<int>> result, 
            int[] candidates, 
            IList<int> combination, 
            int target, 
            int start)
        {
            if (target == 0)
            {
                result.Add(new List<int>(combination));
                return;
            }

            // enforce the combination numbers in the list will be non-descending order
            // brute force the start value from all possible values starting from start variable
            for (int i = start; i != candidates.Length && target >= candidates[i]; ++i)
            {
                combination.Add(candidates[i]);
                CombinationSum(result, candidates, combination, target - candidates[i], i);
                combination.Remove(combination.Last());
            }
        }
}

78. Subsets - Backtracking topic review

78. Subsets - Here is my post on leetcode discuss I wrote on June 22, 2019.


I am reviewing backtracking pattern, here is the article written by a Google engineer. What I like to do is to post all practice first, and then figure out how to master the backtracking pattern.
Here are highlights of my practice:
  1. Start from base case, empty set with no element;
  2. Go over each sublist in the list, add the current element into the sublist.

public class Solution {
    public IList<IList<int>> Subsets(int[] nums)
        {
            if (nums == null)
                return new List<IList<int>>();

            var length = nums.Length;
            var powerSet = new List<IList<int>>(); 

            for (int i = 0; i < length; i++)
            {
                var current = nums[i];

                if (i == 0)
                {
                    var subsets = new List<int>();
                    subsets.Add(current);

                    powerSet.Add(new List<int>());
                    powerSet.Add(subsets);
                }
                else
                {
                    var count = powerSet.Count;

                    for (int j = 0; j < count; j++)
                    {
                        var list = new List<int>(powerSet[j]);
                        list.Add(current);

                        powerSet.Add(list);
                    }
                }
            }

            return powerSet;
        }
}

Leetcode Pattern 3 | Backtracking

Here is the article.

Algorithms:

Leetcode 78. Subsets
90. Subsets II
39. Combination sum
40. Combination Sum II
51. N-Queens

My practice

78. Subsets - submission in May 2019
90. Subsets II - no submission
39. Combination sum - a year ago, two year ago
40. Combination sum II - a year ago, two year ago

78
Here is my post on leetcode discuss I wrote on June 22, 2019.

39
I wrote a post to share on June 22, 2019 based on practice in 2018. Here is the link.
I wrote a post to share on June 22, 2019 based on practice in 2017. Here is the link.

40.
Here is my discussion link for practice in 2018.
Here is my discussion link for practice in 2017.

51
Here is my post written on June 22, 2019. The code was submitted on January 26, 2016. I missed 2016. I got my first Amazon onsite in the city of Vancouver, Canada. I turned 50 years old in October, 2016.

90 
Here is my practice, first one in 2019. The code should be simplified. There are some duplicated code. 

Here is C# practice using recursive solution, I studied the code written by an Amazon engineer. 

TECHNICAL ANALYSIS BASIC EDUCATION OHLC Chart

Here is the article to read.


Moving Average Convergence Divergence (MACD)

Here is the link.


Advance/Decline Line - A/D Definition and Uses

Here is the link.


Simple Moving Average - SMA Definition

Here is the link.


Your Custom Mobile Trading App: Enhanced Positions and Watch Lists

Here is the link.


New Look: TD Ameritrade Platforms Provide Cleaner, Simpler Experience

Here is the link.

I like to get familiar with the design of TD Ameritrade.com website. I start to spend time to track my portfolio, one thing I like to do is to reduce time to spend on the website. I like to learn behind design and where to look for things.


Questrade Tutorial: How To Use The Trading Platform

Here is the article I like to read. I like to save time for me to track my portfolio, and most important is for me to understand the basics first.

As an investor, I have to push myself to learn the basics first. Do not waste time to check portfolio again and again. My ideal time to check balance is once a day.


Top 10 Ways to Defeat Distractions and Get Your Work Done

Here is the link.




Use these 8 productivity hacks when you’re short on time

Here is the link.

1. BLOCK OUT TIME FOR EVERYTHING, NOT JUST MEETINGS

2. DO ONE THING AT A TIME. PERIOD.

3. START EACH WEEK BY WRITING DOWN 1 TO 3 ACTIONS THAT WILL MOVE THE NEEDLE ON YOUR BUSINESS.

4. SCAN YOUR CALENDAR IN ADVANCE. OPTIMIZE WHEN NEEDED

5. RESIST THE TEMPTATION TO PUT OFF CERTAIN INTERNAL MEETINGS

6. SET YOUR PERSPECTIVE AT THE BEGINNING OF EACH DAY

7. NEVER SKIP SELF-CARE

8. DON’T FORGET TO ENJOY IT



NHK纪录片专访过马云后,又专访潘小溪?

Here is the link.




13 Ways to Beat Distractions and Stay Focused at Work

Here is the link.

Pinpoint the problem.
Plan ahead. 
Eat a good breakfast.
Meditate. 
Work offline. 
Do smaller tasks.
Time box. 
Clean up.
Try an app. 
Reward yourself.
Take little breaks.
Wear headphones. 
Try caffeine. 


12,000 startups are being created every day in China

Here is the link.

Friday, June 21, 2019

Leetcode Pattern 4 | Meta Stuff

Here is the link.

I just finished my 10:00 PM mock interview, so I checked the interviewee's linkedin profile. We have a common connection. So I checked the message of the connection. Here is the linkedin profile.

I checked the message on Linkedin.com with the author. It is so amazing that the author will join Google. The chat I had with him is back in January 2018. I just could not believe that time flies, now it is June 21, 2019.

Sourabh Medapati (csgator) sent the following message at 11:08 AM
View Sourabh’s profile




Hello, I read you blog, thanks for providing pointers to my blog. Glad you liked my articles :)! I love practicing on leetcode and I thought the best way to learn is to teach. I plan to write on backtracking next. Also, I am in my internship search, do let me know if you know of anybody hiring summer / fall interns. Thanks, Sourabhreddy Medapati. 
  • jianmin chen 



    Thanks



    I like the one sliding window. That one is great one.



    I like to write c# version based on your example.
  • Sourabh Medapati (csgator) sent the following message at 11:11 AM
    View Sourabh’s profile




    I had a tough time writing the sliding window one and was not sure if I did a good job at explaining the intuition, because it is a bit tricky haha. The topics before that were less tricky.

10 benefits to master a tree algorithm

June 21, 2019

Introduction


It is my short research. I like to write a 10 benefits to master a tree algorithm. Today I was under pressure, since I have to prepare an online code assessment in a week, counting starting from this past Monday, but I still choose to use lowest common ancestor. Why, I should test the algorithm I have problems on, Coin change 2.

10 benefits


I like to use tree algorithm in mock interview, since I learn that dynamic programming will be very easy to write if the interviewee knows the solution.

I will write down my experience here later. 10 benefits, let me write down one at least first.

It is hard to master the tree algorithm called lowest common ancestor. I did ask another tree algorithm over six months over 20 people from 2018 to 2019 called longest univalue path, just after the first time I practiced the easy level tree algorithm on August 2018.

In order to master the tree algorithm lowest common ancestor (LCR), I have to learn how to master the recursive function design, early termination of traversal, preorder/ post order traversal, how to find path from p to root, how to efficiently save the path information for another one to look up, how to work with so many talent people and learn from them.

There are issues related to code performance, tree algorithm in general how to solve using recursive function.

I also need to learn from interviewees, so that I can behave best in problem solving. Figure out how people learn and work with others, solve problem together.


Benefits:

1. I can help interviewee better, drop hint, give quick inside, expedite the process interviewee solves problem;
2. I also challenge myself to learn more about how to analyze problem instead of memorizing all kinds of solutions I learn through interviews;
3. I have to constantly follow up with a practice after mock interview;

I love my failure - timeout code on 518 Coin change 2

June 21, 2019

Introduction


It is so easy to write a dynamic programming solution for Coin change 2. But I spent over one hour to mess with a bug and then fixed the code, my solution has timeout issue. What should I do at the very beginning? Design, show concern about time efficiency, dynamic programming bottom up, more case study on example.


Efficiency


I spent time to learn how to write basic things like copy list using C#, copy list with nested list using C#. I have so much fun to work on them, and I like to write a blog to share it as well.

But in reality I should spend time to learn more important things.

I love to solve a complicated problem. I learn a few things through my practice. Here is the post.

Every day I need to write some code to warm up, even though the code fails to pass online judge, but I enjoy to implement the idea, and learn from the failure.

Here is the link.

C# First practice with timeout issue in 2019

It is a good practice since I have to learn how to write a List<List<int>> and also make the copy list work without using same address in the nested list.
Here are highlights:
  1. The idea is to brute force all possible sequences, including duplicate ones first;
  2. Next step is to remove the duplicate ones by looking up hashset including all keys for each sequence.
Here are failed test cases caught by online judge, I was surprised to learn that I need to work on those issues one by one.
  1. 3, [1, 2, 5], the answer should be 2, not 3
  2. 0, [] should be 1, not 0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _518_Coin_Change_2
{
    class Program
    {
        static void Main(string[] args)
        {
           // var result = Change(3, new int[]{1, 2, 5}); // should be 2
           // var result2 = Change(5, new int[] { 1, 2, 5 }); // should be 3
            var result3 = Change(3, new int[]{2});
        }

        /// <summary>
        /// 518 coin change 2
        /// first get all sequences with duplicate first, and then
        /// remove duplicate count 
        /// 
        /// Time out: 
        /// 500, [1, 2, 5]
        /// </summary>
        /// <param name="amount"></param>
        /// <param name="coins"></param>
        /// <returns></returns>
        public static int Change(int amount, int[] coins)
        {
            if (coins == null || amount < 0)
                return 0;

            if (amount == 0) // caught by online judge: 0,[] should be 1, not 0
                return 1; 

            var F = new int[amount + 1];            
            
            var sequences = new Dictionary<int, List<List<int>>>();
            F[0] = 0;
            sequences.Add(0, new List<List<int>>());

            for (int target = 1; target < amount + 1; target++)
            {
                var newList = new List<List<int>>();
                foreach (var coin in coins)
                {
                    if (coin > target)
                        continue;

                    var search = target - coin;
                    if (!sequences.ContainsKey(search))
                        continue;
                    var list = sequences[search];
                    //var copyList = new List<List<int>>(list); // caught by online judge
                    var copyList = new List<List<int>>();
                    foreach (var subList in list)
                    {
                        var copySubList = new List<int>(subList);
                        copyList.Add(copySubList);
                    }

                    if (copyList.Count == 0)
                    {
                        if (coin == target) // caught by failed test case: 3, [2] should be 0, return 1 instead
                        {
                            var subList = new List<int>(); // caught by debugger
                            subList.Add(coin);
                            copyList.Add(subList);
                        }
                    }
                    else
                    {                        
                        foreach (var sublist in copyList)
                        {
                            sublist.Add(coin);
                        }
                    }

                    newList.AddRange(copyList);
                }

                sequences.Add(target, newList);
            }

            var result = sequences[amount];
            // now it is time to remove duplicate count 
            var hashset = new HashSet<string>();
            int count = 0; 
            foreach (var subList in result)
            {
                // counting sort
                var values = new int[coins.Length];
                var lookupMap = new Dictionary<int, int>();
                for (int i = 0; i < coins.Length; i++)
                {
                    lookupMap.Add(coins[i], i);
                }

                foreach (var value in subList)
                {
                    values[lookupMap[value]]++;
                }

                var key = string.Join("-", values);
                if (hashset.Contains(key))
                    continue;
                hashset.Add(key);
                count++;
            }

            return count; 
        }
    }
}

Case study: My Key Large portfolio performance in a day