Tuesday, November 10, 2020

Leetcode 727 minimum window substring: C# + DP + n subproblems based on subsequence's length

 Nov. 10, 2020

Introduction

It is tough for me to write a C# algorithm using dynamic programming for 727 minimum window substring in less than 20 minutes. My first practice took me over 30 minutes. I like to work on more carefully and write down some good ideas how to solve this algorithm. 

Case study

Case study 1: string "sbsbc", pattern string "sbc"

First of all, the substring "sbsbc" contains subsequence "sbc" which keeps the order as well. But length is 5, shortest one should be "sbc". So in order to get minimum substring, any substring after the first one "sb" should be recorded as well. 

Based on the analysis, it is to work on dp[length + 1], for each i from 1 to length, the largest index containing subsequence "sbc" should be saved. There are length + 1 subproblems. 

In other words, pattern string "sbc", dp[1] is string "sbsbc"'s substring containing subsequence "s"'s start index; largest one should be saved since it can be next shortest length one.
dp[2] is string "sbsbc"'s substring containing subsequence "sb"'s start index; larger index value should replace smaller one. dp[2] starts from value 0, when "sbsbc" is iterated at index = 3, dp[2] is updated with value 2.

Let me walk through "sbsbc", 

first, iterate on first char 's', so dp[1] = 0, length =1 substring starts from index = 0. 

next, iterate on second char 'b', 'b' is second char in pattern string, dp[2] = dp[1] somce dp[1] > 0, so dp[2] = 1, and reset dp[1] = 0. 

thirdly, iterate on third char 's', s is the first char in pattern string, reset dp[1] = 2;

fourthly, iterate on fourth char 'b', b is the second char in pattern string, reset dp[2] = 2, and dp[1] = 0; 

last one, iterate on fifth char 'c', c is the third char in pattern string, set dp[3] = dp[2] since dp[2] > 0, dp[3] = 2. 

Return should be 5 - dp[3] = 5 - 2 = 3. 

Highlights of C# practice

  1. It is important to save pattern chars in count = HashSet<int>[26], since pattern string may have duplicate chars;
  2. More on step 1, pattern string "sbbc", count variable count[1] includes {1, 2}. It is not sorted, not allow duplicate, which is fine with index of position in the pattern string. Convert to list and then sort them. 
  3. Work on count[i] list in decreasing order. 
  4. More on step 1, it is better to use C# HashSet instead of C# SortedSet, no need to maintain sorted order until all are in HashSet first. 
  5. Work on a few more test cases. "sbsbbc", pattern string "sbbc"; one more test case: "sbsbabc", pattern string "sbbc". 

How to design a dp function?

The order of pattern string should be maintained. So dp[i] is designed with variable i being the index of pattern string. 

The string's start position is saved for pattern substring subsequence, which can be used to calculate the length of substring. That is dp[i]'s value. 

Go through each char in string, update matching positions in pattern string's dp values. Cover all subproblems's update. 

Once dp[i]'s value update on last position in pattern string, save the value since one subsequence is found. 

The code has bugs, and I will fix it. 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _727_minimum_window_subsequence
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = FindMinimumWindowSubSequence("sbsbc", "sbc");
            Debug.Assert(result == 3); // "sbc" is found 

            var result2 = FindMinimumWindowSubSequence("sbsbbc", "sbbc");
            Debug.Assert(result2 == 4); // "sbc" is found 

            var result3 = FindMinimumWindowSubSequence("sbsbabc", "sbbc");
            Debug.Assert(result3 == 5); // "sbc" is found 

            var result4 = FindMinimumWindowSubSequence("sbacsbcsbbc", "sbc");
            Debug.Assert(result4 == 3); // "sbc" is found 
        }

        /// <summary>
        /// Nov. 10, 2020
        /// work on "sbsbc", and pattern string "sbc" first
        /// The idea is to define dp array to store start index. 
        /// dp[i] represent p.Substring(0, i) start index (keep updating with biggest one).
        /// For example, pattern string "sbc", dp[1] is to store 's''s information. 
        /// The challenge is to store all subproblems in dp array. 
        /// For example, string s = "sbsbc", when second char "s" shows up in string s, it should be
        /// recorded since it may start another "sbc" with shorter length. 
        /// My idea is to store all chars in pattern string in HashSet<int>[26], and then "b" is visited,
        /// all 'b''s positions in pattern string is traversed by decreasing order, update dp if need.
        /// 'b''s positions in "sbbc" are {1, 2}
        /// </summary>
        /// <param name="s"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static int FindMinimumWindowSubSequence(string s, string p)
        {
            if (s == null || p == null || s.Length < p.Length)
            {
                return -1;
            }

            var pLength = p.Length;
            var dp = new int[pLength + 1];
            var found = new List<int>(); 

            for (int i = 0; i < pLength + 1; i++)
            {
                dp[i] = -1;
            }

            var count = new HashSet<int>[26];
            for (int i = 0; i < 26; i++)
            {
                count[i] = new HashSet<int>();
            }

            for (int i = 0; i < pLength; i++)
            {
                count[p[i] - 'a'].Add(i);
            }

            for (int i = 0; i < s.Length; i++)
            {
                var current = s[i];
                var index = current - 'a';

                var list = count[index].ToList();
                list.Sort();

                for (int j = 0; j < list.Count; j++)
                {
                    // reverse order
                    var next = list[list.Count - j - 1];
                    if (next == 0)
                    {
                        dp[1] = i;
                    }
                    else if (dp[next] >= 0)
                    {
                        dp[next + 1] = dp[next];
                        dp[next] = 0;
                    }

                    // work on next + 1, not next
                    if(next + 1 == pLength && dp[next + 1] >=0)
                    {
                        found.Add(i - dp[next + 1] + 1);
                    }
                }
            }

            return found.Count == 0? -1 : found.Min();
        }
    }
}

AC.TO stock: My favorite stock - missing out

 Nov. 10, 2020

Introduction

It is my missing-out story. I do not want to write more about frustration. I do think that it is more important for me to learn how not to waste time on worrying, talking, instead, I should focus on business, learn more about Air Canada as a business, how the company work hard to survive this coronavirus. 

Air Canada

Air Canada (TSX:AC) investors must have started seeing the light at the end of the tunnel with visible developments on the vaccine front. The airline stock jumped a notable 29% on November 9 and reached its five-month high.

There was a significant surge in Air Canada volume yesterday. More than 27 million shares exchanged hands against its average three-month daily volume of approximately 5 million.

The vaccine news is substantially positive for airline stocks such as Air Canada. A prompter distribution of the same will notably speed up Air Canada’s recovery.

Apart from the vaccine, Air Canada reported much better quarterly numbers yesterday. Its revenue for the third quarter increased by 44% compared to Q2, while losses narrowed as well. Its cash burn slowed to $9 million per day in Q3 against $15 million in the earlier quarter.

While many global airlines are on the verge of filing for bankruptcy, Air Canada is very well-positioned due to its strong balance sheet. Its strong market share and operational efficiency will likely fuel a relatively faster recovery in the post-pandemic environment.

SU.TO: Be a smart retail investor

 Nov. 10, 2020

I like to write down my lesson learned to invest on Suncor stock in short future. Crisis just creates opportunity for a good researcher and also an investor. I show my weakness to talk too much about market risk, my loss, and then do not hold position of Suncor stock 1000 shares. Market risk is hard to get rid of, all institution buyers are also acting on speculation as well. 

Suncor Energy

Suncor Energy (TSX:SU)(NYSE:SU) was unarguably one of the hardest-hit stocks in the energy sector amid the pandemic. It surged almost 25% on the vaccine news yesterday and reach a two-month high. The entire energy sector zoomed after crude oil prices soared 6.6% on November 9.

The integrated energy giant Suncor Energy has lost more than $4 billion in the nine months of 2020. Lower demand for crude oil drove prices lower, ultimately putting a burden on Suncor’s financials.

However, Warren Buffett-led Berkshire Hathaway has been doubling down on Suncor Energy stock for the last couple of quarters. It held more than 19 million shares of Suncor at the end of Q2 2020.

Suncor Energy operates at each node of the energy supply chain. That means it produces oil from its oil sand assets, refines and markets as a finished product. Suncor Energy stock yields a decent 5.5% and looks attractive, particularly for income-seeking investors.

Actionable Items

I should think like a manager. Suncor went up over 20% first day, PPL went up only 6%, and next day on Nov. 10, 2020, it went up 8%. I should think more carefully and bet on PPL.TO and ENB.TO. Just speculate and take some risk. Move on from SU.TO quickly. As an investor, it is important to act quickly and try to reason properly as well. 

If I bet on $60,000 dollars on ENB.TO and PPL.TO on Nov. 10, 2020, I should find good gains already. Stay positive, keep searching. 

Do not stay in the past. Stay in the moment, and figure out what to do next. 

Monday, November 9, 2020

System design: Design a web crawler

 Here is the link. 

DDOS attack 

URL frontier - 

High level design - URL frontier 


Secret to be a good investor: Value the company - not market value

 Nov. 9, 2020

Introduction

It is my job to train myself to be a good equity investor. If I do not learn how to play a good defense, then I will not be a good investor who can enjoy gains like on Nov. 9, 2020. 

Stocks went up over 20%


Air Canada and Suncor

I learn the lesson today since I do not learn to play defense on stock market. I know SU.TO and IMO.TO, AC.TO stocks have lowest price, but I woke up later this morning around 7:30 AM. Suncor went up more than 20%, IMO was still low at that time. 

I did not have any SU.TO or AC.TO stocks. I should anticipate that there are some good news holding until Biden won the election. 




US stock: My watch list on Nov. 9, 2020

 


AC.TO stock: Missing out +4.37+27.62% on Nov. 9, 2020

 


SU.TO: Missing out +3.57 +23/36% on Nov. 9, 2020

 


Sunday, November 8, 2020

System design: System Design Analysis of Google Drive

 Here is the article on medium.com written by Samsung architect. 

Here are highlights about my favorite content:

I will add highlights later. I need to spend more time to learn this topic. 

What will happen when the client is offline?

A client component, Watcher, will observe client-side folders. If any change occurs by the user, it will notify the Index Controller(another client component) about the action of the user. It will also monitor if any change is happening on other clients(devices), which are broadcasted by the Notification server.

When the Metadata service receives an update/upload request, it needs to check with the metadata DB for consistency and then proceed with the update. After that, a notification will be sent to all subscribed devices to report the file update.

Find algorithms to work on: Twitter + programmercoach

 I like to spend at least one hour to go over last 100 weekly contest, and then find some of them to work on. 

If I continuously work on past contests in the weekend, then I can quickly figure out my weakness. Also I need to improve my performance. 

I like to learn a few things from this link. 


Kadane’s Algorithm: Dynamic programming

 Here is the article. 


Saturday, November 7, 2020

Celebration: Google phone screen - another achievement

 Nov. 7, 2020

Introduction

It is my hobby to write blogs and practice algorithms. It is my frugal life style and put my health and fitness in top priority. I did run this Saturday morning starting 8:30 AM in Burnaby central park, and I did have selfies to celebrate, and make this weekend more memorable. 

Google phone screen

It is so unbelievable achievement to pass Google phone screen first time in my life. As a career woman, I recorded a video in central park Burnaby using one app, but it got lost. I plan to go back tomorrow morning to make another one. 




陈建敏,vancouver, BC 16:10

我跑步自拍。庆祝一下谷歌让我进入onsite

陈建敏,vancouver, BC 16:11

我的帽子是谷歌去年西雅图聚会送给我的。

I missed important rebound in stock last two days. So I learn the lesson to stay in the moment. 

There is always risk to take. Always stay positive. 

Here is my youtube video. Here is another video. 


Thursday, November 5, 2020

Leetcode discuss: 1248. Count Number of Nice Subarrays

 Here is the link. 

Second practice - C# - slide window - less than K

Nov. 4, 2020
Introduction
I like to spend 10 minutes to talk about importance to learn to write a simple and elegant solution from lee215. The algorithm can be solved using slide window, and it should take less than 10 minutes.

Slide window
I like to copy the idea using slide window to solve the problem. Here is lee215's solution. I will write down more analysis to make it more clear.

First it is to convert k odd number to another problem using less than k.
Second is to calculate the array with less than k odd number, how many subarrays? For example, [1, 2, 3, 4], k = 2.

public class Solution {
    public int NumberOfSubarrays(int[] A, int k) {
        return atMost(A, k) - atMost(A, k - 1);
    }

    public int atMost(int[] A, int k) {
        var result = 0;
        var left = 0;
        var n = A.Length;
        
        for (int right = 0; right < n; right++) 
        {
            k -= A[right] % 2;
            
            while (k < 0)
            {
                k += A[left] % 2;
                left++;
            }
            
            result += right - left + 1;
        }
        
        return result;
    }
}


Wednesday, November 4, 2020

Progress report: Oct. 4 - Nov. 4, 2020 - 10 things I do better this time

 Nov. 4, 2020

Introduction

I just could not believe that I learn much more because I have to work on small tasks like writing C# for  algorithms. I have to write down 10 things I do better this time to prepare for Google phone screen!

10 things I do better this time

  1. I took Amazon online assessment but I failed the test; I could not speed up my coding and had trouble to play with Hackerrank web compiler using C#. I did it before Google phone screen, one week ahead. 
  2. I started to try to record videos for algorithm practice
  3. I went through a lot of dynamic programming algorithms, I learn how to read other people's sharing
  4. Hard level algorithm is so interesting, and I just could not believe that I waste so many resources. So many people share the solution and it is so easy for me to learn hard level algorithms.  
  5. I started to play leetcode weekly contest after I failed Amazon online code assessment second time in 2020. 
  6. It is most important to expedite my coding. Time is limited. I should practice more. 
  7. I practiced a few times on pramp.com system design and behavior interview. I learned a lot on system design. I started to read Microsoft Microservice book. 
  8. ...

Key largo portfolio: Portfolio update on Nov. 4, 2020


I have less than one hundred dollar gains from last 18 months, but I had chance to purchase so many stocks and learned so many business about United States, coronavirus impact on our economy. 

God blesses United States and Canada. I like this investment so much, keep learning and I just need to be patient, do not gamble too much. Stay small size, learn good money management habit. 


Leetcode discuss: 940. Distinct Subsequences II

 Here is the link. 

Nov. 4, 2020
940. Distinct Subsequences II

Here are steps I took in order for me to learn a hard DP problem.

  1. Read GeeksforGeeks;
  2. Copy C# code, ran into failed test caes;
  3. Learn another C# submission;
  4. Work on a test case

Given a string S, count the number of distinct, non-empty subsequences of S.
Input: "abc"
Output: 7
Explanation: The 7 distinct subsequences are "a", "b", "c", "ab", "ac", "bc", and "abc".

Define C#: var dp = new int[4]; // s = "abc"
dp[3] = length <=3 distinct subsequences
dp[2] = lenght <=2 distinct subsequences

To remove duplicate, use visited two dimension array.
var visited = new int[length + 1][26]
Go over step by step "abc", how to get the result of 7?
Index = 0;
'a' visited[0,0] -> set true
dp [1, 1, 0, 0] 'a'

"a" - distinct subsequence should be one. "a"

Index = 2
start = 0 'b'
visited[0, 1] -> set true
dp [1, 1, 1, 0]
start = 1
visited[1, 1] -> set true
dp [1, 1, 2, 0]

"ab" - distinct subsequence should be three. "a","b","ab"
Thinking, ask to myself?
Q1: dp[2] = 2, explain to myself, what is meaning of 2.
A1: Append 'b' to all subsequence's in the end, "" + "b" = "b", and "a" + "b"= "ab", two more subsequences are added. Make sense?
Q2: What are total subsequence's number?
A2: dp[1] + dp[2] = 3.

Index = 3
start = 0 'c'
visited [0, 2] -> set true
dp [1, 1, 2, 1] <- start = 0
visited[1, 2] -> set true
[1, 1, 2, 2]-> start = 1
visited[2, 2] -> set true
[1, 1, 2, 4] -> start = 2

The idea is simple. First go over all subsequence with 'c', add them together, each one will append 'c' at the end. In the same time, update dp[index] to include 'c' as well. Two tasks should be completed.

"abc" - distinct subsequence should be 7. "a","b","ab", four are added in the last step - index = 3, itself, "c", add "c" after one of each string {"a","b","ab"}.

The total of "abc" distinct subsequence should be 7.

Advice
As a hard working programmer, it is important for me to go over the test case "abc", each step I like to make sure that code will work for those intermediate result.

The order of any subsequence has to be maintained as the original string. The only challenge is to remove duplicated ones.

Time to work on
It took me more than a few hours to study and write down some notes.Patience is the important. Work on a small test case and try to argue to myself what is true here.

It is hard to be an expert on dynamic programming algorithm. Right now, I just like to learn one hard level algorithm. It took me two days, over 8 hours.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _940_distinct_subsequence_II
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = DistinctSubseqII("abc");
        }

        /// study code
        /// https://www.geeksforgeeks.org/count-distinct-subsequences/
        /// I could not make it work, so I studied another one
        /// https://leetcode.com/problems/distinct-subsequences-ii/discuss/560060/Simple-C-DP-Solution
        public static int DistinctSubseqII(string s)
        {
            long MOD    = 1000 * 1000 * 1000 + 7; 
            long result = 0;
            var  length = s.Length;

            var dp      = new long[length + 1];
            var visited = new bool[length + 1, 26];

            dp[0] = 1;

            for (int index = 1; index <= s.Length; index++)
            {
                var endIndex = s[index - 1] - 'a';
                    
                for (int start = 0; start < index; start++)
                {
                    if (!visited[start, endIndex])
                    {
                        visited[start, endIndex] = true;

                        dp[index] += dp[start];
                        result  += dp[start];

                        dp[index] %= MOD;
                        result  %= MOD;
                    }
                }
            }
               
            return (int)result;
        }
    }
}

Actionable Items

Make a youtube video to explain the algorithm. 


How to Use the Dividend Capture Strategy

 Here is the article. 

Dividend Timeline

At the heart of the dividend capture strategy are four key dates:

  • Declaration date: The board of directors announces dividend payment. This is the date when the company declares its dividend. It occurs well in advance of the payment.
  • Ex-dividend date (or ex-date): The security starts to trade without the dividend. This is the cut-off day for being eligible to receive the dividend payment. It's also the day when the stock price often drops in accord with the declared dividend amount. Traders must purchase the stock prior to this critical day.
  • Date of record: Current shareholders on record will receive a dividend This is the day when a company records which shareholders as eligible to receive the dividend.
  • Pay date: This is the day when the dividend is paid and the company issues dividend payments

Sunday, November 1, 2020

Work with peer: Mock interview with a friend

 Thank you for the mock interview using coin change. 


 I wrote two discussion posts. My solution written in mock interview was wrong, I debugged the code and it could not find minimum coins. 

Here is the discussion post. 


I wrote the correct one using BFS, too hard to write, better using dynamic programming. Here is the link. 


Word break algorithm you worked on:
BFS solution Java - I interviewed senior programmer this afternoon working at SAP. Here is the link. 


I wrote C# solution to copy his idea. Here is the link. 

labuladong 的算法小抄

 Here is the link. 

I plan to work on this link and learn a few hours today. It is such a good link for preparing for Google phone screen in a week. 


Leetcode article: Requesting guidance from those who solved 1000+ Leets so far!

 

I spent over 20 minutes to write some ideas to answer the question. 

Read More

I have solved over 1170+ Leetcode problems (including database and shell scripting problems). However, when I try to particular in a weekly coding contest, I can hardly finish all 4 problems (usually only 2 or 3 problems finished) within the 1.5 hrs time window. It seems to me that solving a lot of Leetcode problems in a relatively relaxed setting does not help me very much in competitive programming (under time constrain). And suggestion / advice on how to become more efficient and more competitive in programming contests? Any such suggestion & advice will be much appreciated!

1
Hide 1 reply
Reply
Share
Report
jianminchen's avatar
Read More

I have same concern. I only solved 520 algorithms.
I am trying a few ideas recently. Three things I can think about.

  1. Read Leetcode discuss post from lee215 more often.
  2. Read more blogs from GrandYang on Leetcode.com.
  3. Continue to practice same question, like word break, lowest common ancestor
  4. Go over same type of questions together.
  5. Keep practice. Solve Leetcode using Python language or JavaScript again.

More on item 1, today I copied his code and translated to C#, it took me 10 minutes, but I wrote 40 minutes in weekly contest using my own idea. Lee315 is a great thinker, crafting skill is top level.

More on item 3, I practiced Lowest common ancestor three months, ask the same algorithm three months as an interviewer, but I still fail tree algorithm on weekly contest. I think that problem solving skills cannot be improved on one area like tree algorithm first. We have to work on all of them together.

More on item 4, I reviewed 50 dynamic programming algorithm last week using the link: Leetcode userful links - https://leetcode.com/discuss/general-discussion/665604/important-and-useful-links-from-all-over-the-leetcode/742440

More on item 5. I practice interviews on interviewing dot io last two years over 300+ times. I got a lot of advice how to improve, and I was able to advance my ranking to top 40%, and got invited to interview with startup on interviewing dot io because of my performance as an interviewee last month. But I still could not improve my weekly contest performance. Most of important is to write a lot of code every day, try to write same code shared on Leetcode discuss post, compare difference, and learn more crafting ideas, get smart on debugging and trouble shooting, get used to read code and find bugs quickly. No need to use debugger.

Take some time off to read some books. I like to recommend a book called "The art of readable code". I wish that I read similar book 20 years ago.