Jan. 19, 2022
Introduction
It is the algorithm to sort intervals by start time first, and then end time next. The overlapped intervals should be considered carefully since I made a mistake and the failed test case reminded me the case, which is "the second interval is inside the first interval".
C# | SortedSet<int, int> | Sort the interval | How to merge
It is challenge for me to warmup the algorithm to prepare Microsoft onsite. I like to use SortedSet<Tuple<int,int>> to sort intervals, and also I like to write working code in less than 20 minutes.
I also like to see my growth in terms of problem solving, I like to write C# bug-free code without looking up how to define IComparer.
Failed test case | Learn a quick lesson
It is important for me to practice more algorithms in next month, so that I can perform better on onsite in Feb. 2022. Sometimes I should think about more carefully in terms of analysis.
[[1,4],[2,3]], output: [[1,3]], Expected: [[1,4]]
I changed the definition of end time for overlapped case using Math.Max(previous.Item2, current.Item2)))
The following code passes online judge.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Leetcode_56_merge_intervals
{
class Program
{
static void Main(string[] args)
{
// intervals = [[1,3],[2,6],[8,10],[15,18]]
// output: [[1,6],[8,10],[15,18]]
var intervals = new int[4][];
intervals[0] = new int[] {1, 3};
intervals[1] = new int[] { 2, 6 };
intervals[2] = new int[] { 8, 10 };
intervals[3] = new int[] { 15, 18 };
var result = Merge(intervals);
}
/// <summary>
/// 56 merge intervals
/// Using C# SortedSet<Tuple<start, end>> to sort all intervals using start time first, and then end time
/// </summary>
/// <param name="intervals"></param>
/// <returns></returns>
public static int[][] Merge(int[][] intervals)
{
if (intervals == null || intervals[0] == null || intervals[0].Length == 0)
return new int[0][];
var sorted = new SortedSet<Tuple<int, int>>();
var list2 = new List<Tuple<int, int>>();
foreach (var interval in intervals)
{
list2.Add(new Tuple<int, int>(interval[0], interval[1]));
//sorted.Add(new Tuple<int, int>(interval[0], interval[1]));
}
sorted = new SortedSet<Tuple<int, int>>(list2); // sort once is better than SortedSet.Add one by one
var list = sorted.ToList();
var merged = new List<int[]>();
var previous = (Tuple<int, int>)list[0];
for (int i = 1; i < list.Count; i++)
{
var current = list[i];
var overlapped = previous.Item2 >= current.Item1;
if (overlapped)
{
previous = new Tuple<int, int>(previous.Item1, Math.Max(previous.Item2, current.Item2)); // caught by online judge:[[1,4],[2,3]], output: [[1,3]], Expected: [[1,4]]
}
else
{
merged.Add(new int[] { previous.Item1, previous.Item2 });
previous = new Tuple<int, int>(current.Item1, current.Item2);
}
}
merged.Add(new int[] { previous.Item1, previous.Item2 });
return merged.ToArray();
}
}
}
Follow up | what to learn using C# API | Leetcode discuss C#
Jan. 20, 2022
There are so many ways to apply sorting using C#. I spent near 30 minutes to go over Leetcode discuss and see what to learn from other.
- Array.Sort | Apply rules of sorting, one or two levels;
- LYNQ: Order clause, OrderBy, ThenBy, CompareTo, OrderBy, Aggregate
- Comparer, or define a class to apply IComparer
- SortedSet<Tuple<int, int>>
- Others will be added later.
// 1. OrderBy clause
intervals = intervals.OrderBy(x => x[0]).ToArray();
// 2. List.Sort API
var input = new List<Interval>(intervals);
if(isFirst){
input.Sort((a, b) => ((Interval)a).start >= ((Interval)b).start ? 1 : -1);
}
//3. Array.Sort
Array.Sort(intervals, (arr1, arr2) => arr1[0].CompareTo(arr2[0]));
// 4. OrderBy
intervals = intervals.OrderBy(x=> x[0]).ToArray();
// 5. Array.Sort
Array.Sort(intervals, (op1, op2) => op1[0].CompareTo(op2[0]));
// 6. Array.Sort
Array.Sort(intervals, (a,b) => a[0] - b[0]);
// 7. LYNQ OrderBy
var sortedIntervals=intervals.ToList().OrderBy(x=>x[0]).ToList();
// 8. LYNQ OrderBy, Aggregate
return intervals.OrderBy(x => x.start).Aggregate(new List<Interval>(),
// 9. Array.Sort
Array.Sort(intervals,(x,y)=>{
if(x[0]==y[0])
return x[1].CompareTo(y[1]);
else
return x[0].CompareTo(y[0]);
});
// 10. Array.Sort API and also Comparer class
Array.Sort(intervals, (x, y) => Comparer<int>.Default.Compare(x[0], y[0]));
// 11. Define class Comparer to implement IComparer interface
Array.Sort(intervals, new Comparer());
public class Comparer : IComparer {
int IComparer.Compare( object x, object y ) {
return( ((int[])x)[0] - ((int[])y)[0]);
}
}
// 12. Define class Interval, order by Start first, next order by End if needed
intervals = intervals.OrderBy(x => x.Start).ThenBy(x => x.End).ToList();
class Interval
{
public readonly int Start;
public readonly int End;
public Interval(int start, int end)
{
Start = start;
End = end;
}
}
I will look into more carefully about C# sorting techniques in short future. I choose to use C# SortedSet<Tuple<int, int>> instead of using IComparer. C# System.Lynq is very good choice to write working code if I have time to learn more and practice more.
No comments:
Post a Comment