Last active
June 29, 2017 19:54
-
-
Save jianminchen/74a0264cea06d3886d040018d47f57e8 to your computer and use it in GitHub Desktop.
Code review Leetcode 295 - median of stream - using SortedSet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Leetcode295_medianOfStream | |
{ | |
/// <summary> | |
/// Leetcode 295: | |
/// https://leetcode.com/problems/find-median-from-data-stream/#/description | |
/// Using SortedSet to solve the problem, underneath is binary search tree. | |
/// A few challenges here: | |
/// 1. Go over SortedSet in C#, understand API | |
/// Comparer defintion: | |
/// Comparer<int[]>.Create((a, b) => a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]) | |
/// Max, Min, Count 3 APIs | |
/// | |
/// June 6, 2017 Will figure out how to get more familiar with C# SortedSet | |
/// | |
/// June 29, 2017 | |
/// Read the book Item 31: Implement ordering relations with IComparable<T> | |
/// and IComparer<T> | |
/// Book: Effective C# 50 Specific Ways to Improve Your C# Second Edition Scott Meyers | |
/// | |
/// </summary> | |
class MedianFinder | |
{ | |
static void Main(string[] args) | |
{ | |
//RunTestcase(); | |
RunTestcase2(); | |
} | |
public static void RunTestcase() | |
{ | |
var medianFinder = new MedianFinder(); | |
medianFinder.AddNumber(1); | |
medianFinder.AddNumber(5); | |
medianFinder.AddNumber(3); | |
medianFinder.AddNumber(4); | |
medianFinder.AddNumber(2); | |
var median = medianFinder.FindMedian(); | |
Debug.Assert(median == 3); | |
} | |
public static void RunTestcase2() | |
{ | |
var medianFinder = new MedianFinder(); | |
medianFinder.AddNumber(1); | |
medianFinder.AddNumber(5); | |
medianFinder.AddNumber(3); | |
medianFinder.AddNumber(4); | |
medianFinder.AddNumber(2); | |
medianFinder.AddNumber(6); | |
var median = medianFinder.FindMedian(); | |
Debug.Assert(Math.Abs(median - 3.5) < 0.001); | |
} | |
private int counter = 0; | |
/// <summary> | |
/// code review on June 29, 2017 - need to look into SortedSet<IComparer> | |
/// | |
/// </summary> | |
private SortedSet<int[]> treeLowerHalf = new SortedSet<int[]>( | |
Comparer<int[]>.Create((a, b) => a[0] == b[0] ? a[1] - b[1] : a[0] - b[0])); | |
private SortedSet<int[]> treeUpperHalf = new SortedSet<int[]>( | |
Comparer<int[]>.Create((a, b) => a[0] == b[0] ? a[1] - b[1] : a[0] - b[0])); | |
/// <summary> | |
/// code review on June 29, 2017 | |
/// Keep two tree same size if there are even numbers. If there are odd numbers, | |
/// then first tree called treeLowerHalf will have numbers/2 + 1 numbers. | |
/// | |
/// Need to go over SortedSet API: Add, Remove, | |
/// Property Max[2] and Min[2] | |
/// https://msdn.microsoft.com/en-us/library/dd411719(v=vs.110).aspx | |
/// </summary> | |
/// <param name="number"></param> | |
public void AddNumber(int number) | |
{ | |
var item = new int[] { number, counter++ }; // what is the second number for? | |
int countLower = treeLowerHalf.Count; | |
bool isSameSize = countLower == treeUpperHalf.Count; | |
bool lowerTreeEmpty = countLower == 0; | |
int maxValueLowerTree = lowerTreeEmpty ? int.MinValue : treeLowerHalf.Max[0]; | |
bool lessThanMaxValueLowerTree = number <= maxValueLowerTree; | |
if (isSameSize) | |
{ | |
if (treeLowerHalf.Count == 0 || lessThanMaxValueLowerTree) | |
{ | |
treeLowerHalf.Add(item); | |
} | |
else | |
{ | |
treeUpperHalf.Add(item); | |
// move the minimum number from treeUpperHalf to treeLowerHalf. | |
treeLowerHalf.Add(treeUpperHalf.Min); | |
treeUpperHalf.Remove(treeUpperHalf.Min); | |
} | |
} | |
else if (lessThanMaxValueLowerTree) | |
{ | |
treeLowerHalf.Add(item); | |
// move the maximum number from treeLowerHalf to treeUpperHalf | |
treeUpperHalf.Add(treeLowerHalf.Max); | |
treeLowerHalf.Remove(treeLowerHalf.Max); | |
} | |
else | |
{ | |
treeUpperHalf.Add(item); | |
} | |
} | |
/// <summary> | |
/// Code review on June 29, 2017 | |
/// Return the median of current data stream | |
/// </summary> | |
/// <returns></returns> | |
public double FindMedian() | |
{ | |
if (treeLowerHalf.Count == 0) | |
{ | |
return 0; | |
} | |
if (treeLowerHalf.Count == treeUpperHalf.Count) | |
{ | |
return (treeLowerHalf.Max[0] + treeUpperHalf.Min[0]) / 2d; | |
} | |
else | |
{ | |
return treeLowerHalf.Max[0]; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment