Showing posts sorted by date for query SortedDictionary. Sort by relevance Show all posts
Showing posts sorted by date for query SortedDictionary. Sort by relevance Show all posts

Thursday, April 29, 2021

Leetcode discuss: 1090. Largest Values From Labels

 April 29, 2021

Here is the link. 

C# | greedy algorithm | Two hashmaps to track records | Case study

April 29, 2021
Introduction
I quickly reviewed my own C# code written in 2019, and then made a few changes to speed up the code.

Case study

	 var values = new int[] { 5, 4, 3, 2, 1 };
     var labels = new int[] { 1, 3, 3, 3, 2 };

     var result = LargestValsFromLabels(values, labels, 3, 2);
     Debug.Assert(result == 12);

The question is to ask what is maximum value to find, three numbers, total number of values with same label should not exceed 2. The answer is 12, which is sum of 5 + 4 + 3. The greedy algorithm is applied to find largest value first, and then continue to try to add next smaller one if label count constraint is not broken. The detail is written in the following.

The idea is to put values into C# Dictionary object, a hashmap variable called "map", so values = {5, 4, 3, 2, 1} will be saved into hashmap, for example, first value is 5, label is 1, so map[5] = 1. All values are saved in the following:
map[5] = 1, map[4] = 3, map[3] = 3, map[2] = 3, map[1] = 2.

Next step is to get all keys from hashmap map, and put into an array. Sort the array in descending order. Apply greedy algorithm, go over largest key first, and then choose it into the set if it's label count is still available.

The extra work is to use a hashmap called "used" to track how many numbers are chosed based on label value.

The biggest key is 5, so it is chosen. used hashmap used[5] =1; next biggest key is 4, and 4 is chosen, since value 4's label is 3, so used[3] = 1. Next biggest key is 3, and 3's label is 3, and used[3] = 1 < 2, so 3 can be added to largest value set. All three values are found with sum = 5 + 4 + 3 = 12.

Test case
values = [3,2,3,2,1]
labels = [1,0,2,2,1]
The number in values array may not be unique, so in other words, one number may have different labels. The above test case, the first and third number both are 3, but labels are different. One is 1, second one is 2. In my design, C# variable name map is defined using Dictionary<int, List>, not Dictionary<int, int>.

Simplicity
Avoid using C# SortedDictionary, since keys only needs to be sorted once after all are saved. No need to maintain a SortedDictionary data structure.

The following code was modified based on my previous practice here. The following code passes online judge.

public class Solution {
 static void Main(string[] args)
        {
            RunTestcase2();
        }

        public static void RunTestcase1()
        {
            var values = new int[] { 5, 4, 3, 2, 1 };
            var labels = new int[] { 1, 1, 2, 2, 3 };

            var result = LargestValsFromLabels(values, labels, 3, 1);
            Debug.Assert(result == 9);
        }

        public static void RunTestcase2()
        {
            var values = new int[] { 5, 4, 3, 2, 1 };
            var labels = new int[] { 1, 3, 3, 3, 2 };

            var result = LargestValsFromLabels(values, labels, 3, 2);
            Debug.Assert(result == 12);
        }
		
    public int LargestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit)
        {
            var map = new Dictionary<int, List<int>>();

            var length = values.Length;
            for (int i = 0; i < length; i++)
            {
                var key = values[i];
                var value = labels[i];

                if (!map.ContainsKey(key))
                {
                    map.Add(key, new List<int>());
                }

                map[key].Add(value);
            }

            var usedCount = new Dictionary<int, int>();

           
            var numbers = map.Keys.ToArray();
            Array.Sort(numbers);
        
		    int index = 0;
            length = numbers.Length;
            var sum = 0;            
 
            for (int i = length - 1; i >= 0; i--)
            {
                var key  = numbers[i];
                var list = map[key];

                foreach (var item in list)
                {
                    if (!usedCount.ContainsKey(item))
                    {
                        usedCount.Add(item, 0);
                    }

                    if (usedCount[item] < use_limit)
                    {
                        index++;
                        sum += key;

                        usedCount[item]++;

                        if (index == num_wanted)
                        {
                            return sum; 
                        }
                    }
                }                
            }

            return sum; 
        }
}

Wednesday, February 24, 2021

Leetcode premium: Amazon online assessment

 Feb. 18, 2021 

5. Longest Palindromic Substring
C# | 2021-Feb-18 | two dimension dp | iterate on length from 1 to maximum
C# | 2015-06-15 | dp solution | coding style

  1. K Closest Points to Origin
    C# | 2021-Feb-18 | SortedSet<Tuple<double,int>> | maximum heap with size K
    C# | 2019-Jan-02 | TLE | SortedDictionary
    C# |2019-Jan-02 | TLE | Dictionary<int, HashSet>
    C# | 2019 | timeout is really a challenging problem to solve

Feb. 19, 2021
1258. Synonymous Sentences
C# | mock online assessment | Extra one hour | Union Find | DFS | Copy one line
C# | DFS | Backtracking | Union find | StringComparison.Ordinal | more challenges
1128. Number of Equivalent Domino Pairs
C# | Counting sort | Combination subroutine | 2021-Feb-18

Feb. 18, 2021
346. Moving Average from Data Stream
C# | Queue | actual size not maximum | O(1) to remove first one and add current one
1331. Rank Transform of an Array
C# | Sorting | distinct values | 2-18-2021

  1. Sum of Root To Leaf Binary Numbers
    C# | Mock online assessment | Tree | Recursive | Calculation challenge | 2021-Feb-19

  2. Two Sum BSTs
    C# | 2021-02-18 | preorder traversal | two hashSets

  3. Rank Transform of an Array
    C# | Sorting | distinct values | 2-18-2021

  4. Spiral Matrix II
    C# | 2021-02-18 | direction array | visited array | automatic direction change | clockwise

  5. Rotting Oranges
    C# | BFS | Starting from rotten orange | 2021-02-18

Leetcode premium | Mock onsite interviews
Google mock onsite
Microsoft mock onsite
Facebook mock onsite
Facebook mock online assessment
Amazon online assessment

Friday, June 12, 2020

Leetcode discuss: 23. Merge k Sorted Lists

Here is the post.

June 11, 2020
23 minimum Heap - merge k sorted lists
Merge k sorted lists to one sorted linked list.
The algorithm is challenge to work on. The linked list is important data structure and it takes me a lot of practice. I solved over 30 linked list algorithms in my 2018 practice on Leetcode, and also on Hackerrank. Here is the blog to show my practice of linkedlist.
Merge sort is also popular algorithm in data structure and algorithm course. The master theorem is not tough for me since I have math bachelor degree from 1984 to 1988.
How to design a minimum heap using C# SortedDictionary<int, Queue<List>>? It is interesting to review the code written in 2018 and 2019.
What I missed from 2015 to 2019 is to write down a case study, and explain the thing from problem statement, idea to solve, go over a case study, explain the solution step by step. I like this case study method from Harvard business school teaching The HBS Case Method. I like to apply my practice as well, and I will be expert to write case study for algorithms in short future.
I also like to take some time to review how to write a showcase class with good object-oriented design, and also review those C# interface IEnumerable etc.
"23 merge k sorted lists" is a hard level algorithm. Please take a look my related showcase of easy level, medium level algorithm using minimum heap.
  1. Third Maximum Number, link is here.


Friday, June 5, 2020

Leetcode discuss: 215. Kth Largest Element in an Array

Here is the post.

C# SortedDictionary minimum heap practice in 2020

June 4, 2020
Find kth largest element is very classical algorithm. I work on two tricky things to convert the problem into a minimum heap problem.
Warmup and best design talk
Let us walk through an example, how to design data structure heap for the help.
For example, integer array [1, 2, 3, 4, 5,6,7,8,9,10], k = 2
Minimum heap
Every number has to be went through, so the last one the heap should be [9, 10], the size is 2.
9 is the top of minimum heap.
Another example, still [1, 9, 2, 3, 4, 5, 6, 7, 8, 10], the last one the heap still should be [9, 10], the size is 2. Kth number is the top of heap.
The size of heap is important to find kth number in minimum heap. k = 2, heap size is 2.
If the array size is 10,000, number from 1 to 10,000, and then kth number is 9995, why we keep heap size as 9995, it is better to reverse the array in ascending order using -10,000 to -1. So the heap size can be 5 instead of 9995.
The exercise is warmup our design muscle and have a short break ice for real coding work.
Maximum heap
Since maximum heap can be processed using negative value of element array. We can stay with the minimum heap all the time.
Two tips
Work on a test case, array, [1, 2, 3, 4, 5], kth largest element, for example, 2th largest element is the fourth smallest element. Both are 4.
In order to apply kth largest element problem, it is to save -1 * element value. So largest one is converted into smallest one.If k is very big number close to size of array, then -1 * element will make sense, because n - k + 1 will be small integer, the minimum heap's size is small one.
Here are my highlights:
  1. Design a minimum heap using SortedDictionary<int, int>, key is -1 * element value, value is count of element value; Notice that largest kth element not largest kth distinct element;
  2. Write a class called MinHeap, two APIs, one is called Add(int val), second one is PopMin(), public property called sorted using SortedDictionary<int, int>;
  3. Work on test case [1, 2, 3, 4,5], k = 2, 2th largest one is 4, and it is 4th smallest one. k -> n - k + 1 is the conversion mapping;
  4. In order to get kth smallest minimum element, the heap size should be n - k + 1 at most.
Tips to share
I wrote a solution using minimum heap to find 814: third largest distinct element in the array, similar idea. The post is here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _215_kth_largest_element
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        /// <summary>
        /// First practice: June 4, 2020
        /// </summary>
        public class MinHeap
        {
            /// <summary>
            /// use SortedDictionary to implement the minimum heap              
            /// </summary>
            public SortedDictionary<int, int> sorted = new SortedDictionary<int, int>();

            public void Add(int val)
            {
                if (sorted.ContainsKey(val))
                {
                    sorted[val]++;
                }
                else
                {
                    sorted.Add(val, 1); 
                }
            }

            /// <summary>
            /// SortedDictionary<int> default is in ascending order. 
            /// 
            /// </summary>
            /// <returns></returns>
            public int PopMin()
            {
                int minKey = sorted.Keys.First();

                var count = sorted[minKey];
                if (count == 1)
                {
                    sorted.Remove(minKey);
                }
                else
                {
                    sorted[minKey]--;
                }

                return minKey;
            }
        }

        /// <summary>
        /// Find kth largest element in the array, not kth largest distinct element
        /// Save each element value * -1, so kth largest one will be (n - k + 1)th smallest one. 
        /// </summary>
        /// <param name="nums"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public int FindKthLargest(int[] nums, int k)
        {            
            if (nums == null || nums.Length == 0 || k < 0)
                return -1;

            k = nums.Length - k + 1; // convert largest kth to smallest 

            var length = nums.Length;
            var heap = new MinHeap();            
          
            // Let us keep min heap size as k all the time
            // In other words, add one number to the heap, 
            // move the minimum one in the heap as well if heap's size is bigger than k. 
            int size = 0; 
            
            for (int i = 0; i < length; i++)
            {
                var negativeValue = -1 * nums[i];
                size++; 

                heap.Add(negativeValue);

                if (size > k)
                {
                    heap.PopMin();
                }
            }

            return -1 * heap.PopMin();
        }
    }
}


Leetcode discuss: 215. Kth Largest Element in an Array

June 5, 2020

Here is the post.

C# SortedDictionary minimum heap practice II in June 2020

It is my second practice on this algorithm. I found out that my first practice has a unnecessary work to save -1 * element value in the array to minimujm heap. Here is the first practice. I think that my first practice shows weakness of my analytical skills using minimum heap; I should argue that minimum heap can deal with kth largest element algorithm perfectly, without using maximum heap.
Case study
Given an array, find kth largest element in the array. For example, array [1, 2, 3, 4, 5], k = 2, so kth largest element is value 4, index position = 3; We have to iterate all numbers in the array in order to find kth largest one.
If minimum heap is kept to size k, then kth largest one will be on top of minimum heap after last element is visited.
Kth largest element in the array can be solved using minimum heap, and heap size is also k. If k is not too largest, heap size is not an issue, then I just choose to go ahead to save element value in minimum heap; otherwise I can play the trick to save -1 * element value to reduce heap size.
Here are higlights:
  1. Design a minimum heap and understand the importance to keep minimum heap size as k;
  2. Use C# SortedDictionary<int, int> strong typing, value data type is count of same element value in the array;
  3. Look into other C# data structure which may be best choice compared to SortedDictionary<int, int>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _215_kth_largest_element
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        /// <summary>
        /// First practice: June 4, 2020
        /// </summary>
        public class MinHeap
        {
            /// <summary>
            /// use SortedDictionary to implement the minimum heap              
            /// </summary>
            public SortedDictionary<int, int> sorted = new SortedDictionary<int, int>();

            public void Add(int val)
            {
                if (sorted.ContainsKey(val))
                {
                    sorted[val]++;
                }
                else
                {
                    sorted.Add(val, 1);
                }
            }

            /// <summary>
            /// SortedDictionary<int> default is in ascending order. 
            /// 
            /// </summary>
            /// <returns></returns>
            public int PopMin()
            {
                int minKey = sorted.Keys.First();

                var count = sorted[minKey];
                if (count == 1)
                {
                    sorted.Remove(minKey);
                }
                else
                {
                    sorted[minKey]--;
                }

                return minKey;
            }
        }

        /// <summary>
        /// Find kth largest element in the array, not kth largest distinct element
        /// For example, [1, 2, 3, 4, 5], kth largest element is 4 if k = 2; how to find 4? 
        /// All elements should be searched, last one is 5, kth one should be minimum one on the top. 
        /// The tricky part is to keep minimum heap size as k
        /// </summary>
        /// <param name="nums"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public int FindKthLargest(int[] nums, int k)
        {
            if (nums == null || nums.Length == 0 || k < 0)
                return -1;            

            var length = nums.Length;
            var heap = new MinHeap();

            // Let us keep min heap size as k all the time
            // In other words, add one number to the heap, 
            // move the minimum one in the heap as well if heap's size is bigger than k. 
            int size = 0;

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

                heap.Add(value);

                if (size > k)
                {
                    heap.PopMin();
                }
            }

            return heap.PopMin();
        }
    }
}
treesminimum heapc# sorteddictionary

Saturday, October 5, 2019

1046. Last Stone Weight

Here is my discussion post.

The algorithm can be solved using minimum heap. To convert maximum two numbers to minimum two numbers, negative value is used instead.
Here are highlights:
  1. Understand C# SortedDictionary can be used to impelement minimum heap first;
  2. Apply all ement value to negative one, so maximum heap turns into a minimum heap problem;
  3. Get familiar with IEnumberable First API and it can be used to get the minimum one from the heap.
public class Solution {
    /// <summary>
        /// Oct.4, 2019
        /// Implement a maximum heap - 
        /// what I can do is to use negative value 
        /// </summary>
        /// <param name="stones"></param>
        /// <returns></returns>
        public int LastStoneWeight(int[] stones)
        {
            var sorted = new SortedDictionary<int, int>();

            // put all numbers into minimum heap - default - negative value
            foreach (var number in stones)
            {
                var key = number * (-1);
                if (!sorted.ContainsKey(key))
                {
                    sorted.Add(key, 0);
                }

                sorted[key]++; 
            }

            while (!((sorted.Keys.Count == 1 && sorted[sorted.Keys.ToList()[0]] == 1) || sorted.Keys.Count == 0))
            {
                // get minimum two values from minimum heap
                var key = sorted.Keys.First();
                var hasAtLeastTwo = sorted[key] > 1;
                if (hasAtLeastTwo)
                {
                    sorted[key] -= 2;
                    if(sorted[key] == 0)
                    {
                        sorted.Remove(key);
                    }
                }
                else 
                {
                    var minimum = key;
                    sorted.Remove(key);
                    var next = sorted.Keys.First();
                    sorted[next]--;

                    if (sorted[next] == 0)
                    {
                        sorted.Remove(next);
                    }

                    var diff = Math.Abs(minimum - next);
                    var newKey = diff * (-1);

                    if (newKey == 0)
                        continue;

                    if (!sorted.ContainsKey(newKey))
                    {
                        sorted.Add(newKey, 0);
                    }

                    sorted[newKey]++;
                }                
            }

            if (sorted.Keys.Count == 0)
                return 0;

            return sorted.Keys.ToList()[0] * (-1);
        }
}