Wednesday, January 6, 2021

Leetcode discuss: 1439. Find the Kth Smallest Sum of a Matrix With Sorted Rows

 Here is the link. 

First practice - C# - TLE 35/71 - DFS

Jan. 5, 2020
Introduction
It is the last algorithm in one of mock onsite on Leetcode premium. I spent over one hour but I could not figure out working solution - not brute force. It is hard to figure out next smaller. After the mock session, I wrote a DFS solution and then ran into TLE error.

Test case 35/ 71
Timeout - I will quickly figure out how to fix this issue. I believe that I should apply some pruning so it will be able to avoid TLE.

Time compleixty
DFS algorithm will exhaust all options, upper bound will be related to columns^ rows, which is the number of sequence, in which one for each row.

The working solution will take less than 20 minutes to write, and time complexity can be low as O(rows * k * columns * log(k * columns)).
Here is my working solution.

My first one hour
I spent one hour in mock interview, but I could not figure out a working solution.

Here are lesson learned:

  1. Work on time complexity analysis - brute force, how to lower the the time compleixty
  2. Brute force, find all sequence in which one number is selected for each row, the combinations are columns^rows. It will time out.
  3. Next, work on exactly get next smallest sum for sequence - it is too hard to search - beyond a hard level
  4. Next, relax the condition, each row, find kth smallest numbers. Easy task;
  5. Start from second row, consider sequence of two numbers, keep kth smallest sequence as well. Time complexity, sorting, total upper bound of number - k * columns.
  6. What did I miss in mock interview? Will add later.
  7. Take a row by row solution, work on one row at a time. Next work on combination of two rows, sum of two number sequence, find kth smallest one.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _1439_kth_element
{
    class Program
    {
        static void Main(string[] args)
        {
            var mat = new int[2][];

            mat[0] = new int[] { 1, 3, 11};
            mat[1] = new int[] { 2, 4,  6};

            var result = KthSmallest(mat, 5);
            Debug.Assert(result == 7); 
        }

        public static int KthSmallest(int[][] mat, int k)
        {
            if (mat == null || mat.Length == 0 || mat[0].Length == 0)
            {
                return -1;
            }

            var rows    = mat.Length;
            var columns = mat[0].Length;

            var sorted = new SortedSet<Tuple<int, int>>();
            var list  = new List<int>();
            var index = 0; 

            runDFS(mat, k, sorted, 0, list, ref index);

            return sorted.Last().Item1; 
        }

        private static void runDFS(int[][] mat, int k, SortedSet<Tuple<int, int>> sorted, int row, List<int> list, ref int index)
        {
            if (row >= mat.Length)
            {
                var total = list.Sum(); 

                if (sorted.Count < k)
                {
                    sorted.Add(new Tuple<int, int>(total, index++));
                }
                else if (sorted.Count == k && sorted.Last().Item1 > total)
                {
                    sorted.Remove(sorted.Last());
                    sorted.Add(new Tuple<int,int>(total, index++));
                }

                return;
            }

            var rows = mat.Length;
            var columns = mat[0].Length;

            for (int col = 0; col < columns; col++)
            {
                var current = mat[row][col];

                // check the sum so far - compare to sorted
                if (sorted.Count == k && sorted.Last().Item1 < list.Sum() + current)
                {                    
                    break;                    
                }

                list.Add(mat[row][col]);

                runDFS(mat, k, sorted, row + 1, list, ref index);

                list.RemoveAt(list.Count - 1);
            }
        }
    }
}

Leetcode discuss: 123. Best Time to Buy and Sell Stock III

 Here is the link. 

C# - mock interview - performance - design issue

Jan. 6, 2020
It is challenge for me to analyze this written solution in mock onsite interview, how to quickly modify the design to make it work, fix TLE error.

The TLE problem
The function I designed called MaxProfitOneTrade takes O(N) time for each start variable.
It should be simplifyed using dynamic programming to make it O(1).

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

namespace stockTradeII
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = MaxProfit(new int[]{1, 2});
        }

        public static int MaxProfit(int[] prices)
        {
            if (prices == null || prices.Length < 4)
            {
                return 0;
            }

            var length = prices.Length;
            var twoOrderProfit = 0;

            // at most 2 
            for (int i = 0; i + 1 < length; i++)
            {
                var first = MaxProfitOneTrade(prices, 0, i);
                var second = MaxProfitOneTrade(prices, i, length - i);
                var current = first + second;
                twoOrderProfit = current > twoOrderProfit ? current : twoOrderProfit;
            }

            return twoOrderProfit;
        }

        /// <summary>
        /// the problem of the design is time complexity
        /// O(N), it can be O(1), using extra space, save all profit for each position
        /// </summary>
        /// <param name="prices"></param>
        /// <param name="start"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        private static int MaxProfitOneTrade(int[] prices, int start, int length)
        {
            if (prices == null || length == 0)
            {
                return 0;
            }

            var minPrice = prices[start];
            var maxProfit = 0;

            for (int i = start + 1; i < start + length; i++)
            {
                var current = prices[i];
                var isSmaller = current < minPrice;
                if (isSmaller)
                {
                    minPrice = current;
                }
                else
                {
                    var profit = current - minPrice;
                    maxProfit = profit > maxProfit ? profit : maxProfit;
                }
            }

            return maxProfit;
        }
    }
}

Leetcode discuss: 123. Best Time to Buy and Sell Stock III

Here is the link. 

C# - dynamic programming - case study - choose DP first always

Jan. 6, 2020

This solution is based on the Best Time to Buy and Sell Stock (Easy level) where you track the global minimum price and maximum profit. At most two trades are considered, so the important task is to divide the array into two areas.

Go left to right, and store the best profit for each day individually in left.
left[i] shows the max profit for days [1, i]

Go right to left, store best profit in right
right[i] shows the max profit for days [i + 1, n]

The maximum profit is the maximum of left[i] + right[i] for i = 0 to n - 1.

Case study
Input: prices = [3,3,5,0,0,3,1,4]
Output: 6

The idea is to find at most two trades to make maximum profit. The array interval can be divided into two intervals. There are at most n ways to divide.

It is to think about dynamic programming way to use exisitng calculated solution.
[3, 3, 5], how to calculate the maximum profit for one trade in the interval, last index is 2, value 5, only need to find minimum value in previous interval.
left[2] = Math.Max(left[1], 5 - minPrice[i - 1]).

Just consider current price 5 to calculate it's maximum profit value.

[0,0,3,1,4]
this one is to work from right to left iteration order. Index position is 4, value 0, the maximum profit to purchast at index = 4 is to find maximum profit in right side of the index = 4.

public class Solution {
    // at most two trades - maximum profit
        // dynamic programming solution
        // 
        public int MaxProfit(int[] prices) 
        {
            var n = prices.Length;

            var minLeft = Int32.MaxValue;
            var maxRight = 0;
            var maxProfit = 0;

            var left  = new int[n + 1]; 
            var right = new int[n + 1];

            // interval from [0, i]
            for (int i = 0; i < n; ++i) 
            {
                var price  = prices[i];                

                minLeft     = Math.Min(minLeft, price);                
                left[i + 1] = Math.Max(left[i], price - minLeft);                
            }

            // interval from [n - i - 1, n)
            for (int i = 0; i < n; ++i)
            {                
                var price = prices[n - i - 1];
                
                maxRight = Math.Max(maxRight, price);               
                right[n - i - 1] = Math.Max(right[n - i], maxRight - price);
            }

            // at most two trades
            for (int i = 0; i < n; i++ )
            {
                maxProfit = Math.Max(maxProfit, left[i] + right[i]);
            }
            
            return maxProfit;            
        }
}

 

Leetcode discuss: 839. Similar String Groups

 Here is the link. 

Second practice - C# - Union Find - Union API lesson learned

Jan. 6, 2020

I wrote the working solution after the bug fix - Union API functionality. Since the code I wrote in mock interview failed on one test case, I learned the lesson. The failed practice is here.

Importance
It took me more than a hour to learn to fix the problem after the mock interview. I need to be humble and stay cautious on wrong answer to apply Union Find algorithm.

public class Solution {
    // union find algorithm    
        public int NumSimilarGroups(string[] strs)
        {
            if (strs == null || strs.Length <= 1)
                return 0;

            var length = strs.Length;
            var parents = new int[length];

            for (int i = 0; i < length; i++)
            {
                parents[i] = i;
            }            

            for (int i = 0; i < length - 1; i++)
            {
                var first = strs[i];

                for (int j = i + 1; j < length; j++)
                {
                    var second = strs[j];
                    
                    if (runSimilarCheck(first, second))
                    {
                        parents[FindParent(j, parents)] = FindParent(i, parents);
                    }                    
                }
            }

            // run again 
            for (int i = 0; i < length; i++)
            {
                parents[i] = FindParent(i, parents);
            }

            var count = 0;
            for (int i = 0; i < length; i++)
            {
                if (i == parents[i])
                {
                    count++;
                }
            }

            return count;
        }

        private static bool runSimilarCheck(string s1, string s2)
        {
            var length = s1.Length;
           
            var count = 0;

            for (int i = 0; i < length; i++)
            {
                if (s1[i] != s2[i])
                {
                    count++;                    
                }
            }            

            // since s1 and s2 are anagram, there is no need to compare chars between s1 and s2. 
            return count <= 2 ;
        }

        private static int FindParent(int start, int[] parents)
        {
            if (start != parents[start])
            {
                parents[start] = FindParent(parents[start], parents);
            }

            return parents[start];
        }
}

Leetcode discuss: 839. Similar String Groups

 Here is the link. 

Lesson learned - C# - Union Find - FindParent API - Union API - Failed

Jan. 6, 2020
Introduction
It is the last algorithm of my Leetcode mock facebook onsite interview. I wrote Union Find algorithm and came cross failed test case.

Failed test case - 60/77
"kccomwcgcs","socgcmcwkc","sgckwcmcoc","coswcmcgkc","cowkccmsgc","cosgmccwkc","sgmkwcccoc","coswmccgkc","kowcccmsgc","kgcomwcccs
The string is marked using index starting from 0.
0 - kccomwcgcs
1 - socgcmcwkc
2 - sgckwcmcoc
3 - coswcmcgkc
4 - cowkccmsgc
5 - cosgmccwkc
6 - sgmkwcccoc
7 - coswmccgkc
The string is denoted as strs, so strs[3] and strs[7] are similar, so Parents[7] = 3; later strs[5] and strs[7] are similar, so Parents[7] = 5; actually the first one is to union 3 and 5, second one is to union 5 and 7. But my code turned out missing first similar pair 3 and 7.

The parents array is wrong, the detail is the following:
parent[0] = 0,
parent[1] = 1
parent[2] = 2
parent[3] = 3
parent[4] = 4
parent[5] = 5
parent[6] = 2
parent[7] = 5
parent[8] = 4
parent[9] = 0

Actually parent[7] = 3, parent[7] = 5, so 3, and 5 and 7 should be one group. One of correct solution is the following:
parent[0] = 0,
parent[1] = 1
parent[2] = 2
parent[3] = 5
parent[4] = 4
parent[5] = 5
parent[6] = 2
parent[7] = 5
parent[8] = 4
parent[9] = 0

What is happening?
The statement in the following should be corrected:

parents[j] = FindParent(i, parents);

It should be:

parents[FindParent(j, parents)] = FindParent(i, parents);

The following code could not pass online judge. I wrote in my Leetcode premium Facebook mock interview.

Union API
The union API should be remembered. There are two FindParent calls in the statement.

public class Solution {
    // union find algorithm
    public int NumSimilarGroups(string[] strs) {
        if(strs == null || strs.Length <= 1)
            return 0; 
        
        var length = strs.Length;         
        var parents = new int[length];
        
        for(int i = 0; i < length; i++)
        {
            parents[i] = i; 
        }
        
        for(int i = 0; i < length - 1; i++)
        {
            var first = strs[i];
            
            for(int j = i + 1; j < length; j++)
            {
                var second = strs[j]; 
                
                if(runSimilarCheck(first, second))
                {                     
                    parents[j] = FindParent(i, parents); // Union i and j API - it should have two FindParent API calls in the statement - added after mock interview onsite
                }
            }
        }
        
        // run again 
        for(int i = 0; i < length; i++)
        {
            parents[i] = FindParent(i, parents);
        }
        
        var count = 0; 
        for(int i = 0 ; i < length; i++)
        {
            if(i == parents[i])
            {
                count++; 
            }
        }
        
        return count; 
    }
    
    private bool runSimilarCheck(string s1, string s2)
    {
        var length = s1.Length; 
        
        var first = -1; 
        var second = -1; 
        var count = 0; 
        
        for(int i = 0; i < length; i++)
        {
            if(s1[i] != s2[i])
            {
                count++; 
                if(first == -1)
                {
                    first = i; 
                }
                else if(second == -1)
                {
                    second = i; 
                }
            }
        }
        
        return count == 0 || (count == 2 && s1[first] == s2[second] && s1[second] == s2[first]); 
    }
    
    private int FindParent(int start, int[] parents)
    {
        if(start != parents[start])
        {
            parents[start] = FindParent(parents[start], parents);
        }
        
        return parents[start];
    }
}

Sven Carlin: My Strategy For 2021 Stock Market Crash + Probabilistic Outlook!

 Here is the link. 

There is a 14% chance of a 42% stock market crash happening in 2021. On average a market crash, thus a drop larger than 20% happens every 6.92 years. This is a given as we have had 13 stock market crashes since 1928. As it is a given, the key is to have a strategy because you can't predict a crash, you can only take advantage of one if you understand what you are buying and adjust for the probabilities in the market. 0:00 Stock Market Crash 1:00 Key Crash Factor 1:50 Chances for Crash 7:19 Crash Strategy 8:47 My Strategy


Sven Carlin: Intel Stock - I'm Buying For Earnings, Dividends & Buybacks

 Here is the link.


An Intel Stock Analysis has been what most of you requested so, because the stock is down but has good fundamentals and offers a very positive outlook, I went into a deep analysis. I also bought Intel stock for my portfolios because the risk and reward is on the positive investing side despite the murky short term outlook that many analysts have. When it comes to buying Intel stock, one has to differentiate between the negative news or noise that has pushed Intel's stock price below $50 and the fundamentals that still look good with high cash flows, strong buybacks and a growing dividend. Intel will definitely lose market share as the environment it operates is more and more competitive, but what is a key investment factor, the semiconductor sector is a growth one, and Intel can keep growing no matter the competition. AMD, NVDA, QCOM and others will do their thing for sure and eat into INtel's moat, but it is most likely Intel will keep growing. In a conservative growth scenario of just 3% per year, and investment into Intel now would likely lead to great long term returns and that is why Intel is a stock to buy now. There are also risks, Intel could end up like IBM, but it is more likely it will end up like Apple stock. Intel now reminds me of Apple in 2016 because the fundamentals were there but the analysts were all worries about the lack of innovation with the new iPhone and consequently lower revenue growth and no profit growth. They were completely right, but the stock went from $100 to the current $500. Enjoy the video: 00:00 Intel stock analysis 01:52 Intel stock price 05:13 Why Intel stock down? 06:29 Analysts downgrades 09:34 Market noise 11:34 Business environment 14:37 Business outlook 16:14 Intel growth potential 17:14 Intel Q2 Earnings 17:57 Comparison to AMD, NVDA 19:00 Intel guidance 20:09 Fundamentals 21:59 Intel buybacks 22:39 Apple comparison 23:49 $10 billion buyback effect 24:37 Intel CEO 24:58 Intel dividend 25:36 Intel stock valuation 27:26 Risk and reward