private SkyLine FindSkyline(Building[] building, int low, int high) { //here when we divide and seperate recursion there are two possibilities //low will be equal to high //if we handle low = high, low won't be greater to high and high won't go lesser than low if (low == high) { //You have one building, get skylines from the building //eg (1,11,5) will give (1,11) and (5,0) // update 06/28/2017 // A skyline is a collection of rectangular strips. // A rectangular strip is represented as a pair (left, ht) where left is x coordinate of left side of strip and ht is height of strip // here (5, 0) because 5 is the x corordinate of the left side of the strip (2nd strip) of height 0. .. SkyLine result = new SkyLine(2); result.append(new Strip(building[low].left, building[low].height)); result.append(new Strip(building[low].right, 0)); return(result); } //default case low will be lesser than high int middle = (low + high) / 2; SkyLine skyline1 = FindSkyline(building, low, middle); SkyLine skyline2 = FindSkyline(building, middle + 1, high); //order is important here merge skyline1 to skyline2 return(MergeTwoSkylines(skyline1, skyline2)); }
//Note: order is important. This function append the skyline2 to skyline1 //same as calling skyline1.merge(skyline2) public SkyLine MergeTwoSkylines(SkyLine skyline1, SkyLine skyline2) { // Create a resultant skyline with capacity as sum of two // skylines SkyLine result = new SkyLine(skyline1.GetSize() + skyline2.GetSize()); // The idea is similar to merge of merge sort, start from first strips of two skylines, compare x coordinates. //Pick the strip with smaller x coordinate and add it to result. //The height of added strip is considered as maximum of current heights from skyline1 and skyline2. //Example to show working of merge: // Height of new Strip is always obtained by takin maximum of following // (a) Current height from skyline1, say 'h1'. // (b) Current height from skyline2, say 'h2' // h1 and h2 are initialized as 0. h1 is updated when a strip from // SkyLine1 is added to result and h2 is updated when a strip from // SkyLine2 is added. int h1 = 0, h2 = 0; int leftpointer = 0; //left half pointer int rightpointer = 0; //right half pointer while (leftpointer < skyline1.GetSize() && rightpointer < skyline2.GetSize()) { int mergeheight = 0; if (skyline1.strips[leftpointer].left < skyline2.strips[rightpointer].left) { h1 = skyline1.strips[leftpointer].height; mergeheight = Math.Max(h1, h2); result.append(new Strip(skyline1.strips[leftpointer].left, mergeheight)); leftpointer++; } else { //don't worry about equal condition. result.append already has logic to skip skyline if the previous skyline has same height and left h2 = skyline2.strips[rightpointer].height; mergeheight = Math.Max(h1, h2); result.append(new Strip(skyline2.strips[rightpointer].left, mergeheight)); rightpointer++; } } // If there are strips left in this skyline or other // skyline while (leftpointer < skyline1.GetSize()) { result.append(skyline1.strips[leftpointer]); leftpointer++; } while (rightpointer < skyline2.GetSize()) { result.append(skyline2.strips[rightpointer]); rightpointer++; } return(result); }
private SkyLine GetSkylinesFromSingleBuilding(Building building) { //there are two strips for single building SkyLine result = new SkyLine(2); result.append(new Strip(building.left, building.height)); result.append(new Strip(building.right, 0)); return(result); }
private void button1_Click(object sender, EventArgs e) { // Input: Array of buildings //{ (1,11,5), (2,6,7), (3,13,9), (12,7,16), (14,3,25), // (19,18,22), (23,13,29), (24,4,28) } List <Building> buildings = new List <Building>(); Building building1 = new Building(1, 11, 5); Building building2 = new Building(2, 6, 7); Building building3 = new Building(3, 13, 9); Building building4 = new Building(12, 7, 16); Building building5 = new Building(14, 3, 25); Building building6 = new Building(19, 18, 22); Building building7 = new Building(23, 13, 29); Building building8 = new Building(24, 4, 28); buildings.Add(building1); buildings.Add(building2); //buildings.Add(building3); //buildings.Add(building4); //buildings.Add(building5); //buildings.Add(building6); //buildings.Add(building7); //buildings.Add(building8); SkyLine result = FindSkyline(buildings.ToArray(), 0, buildings.Count - 1); StringBuilder sb = new StringBuilder(); foreach (Strip s in result.strips) { if (s != null) { sb.Append("(").Append(s.left).Append(",").Append(s.height).Append(")"); } } string output = sb.ToString(); // Skyline for given buildings is //(1, 11), (3, 13), (9, 0), (12, 7), (16, 3), (19, 18), //(22, 3), (23, 13), (29, 0), }
private SkyLine GetSkyline(List <Building> buildings) { SkyLine result = null; foreach (Building building in buildings) { SkyLine skyline = GetSkylinesFromSingleBuilding(building); if (result == null) { result = skyline; } else { result = MergeTwoSkylines(result, skyline); } } return(result); }