|
342 | 342 | " assert actual == expected, f\"{matrix,val}: {expected} != {actual}\"" |
343 | 343 | ] |
344 | 344 | }, |
345 | | - { |
346 | | - "cell_type": "markdown", |
347 | | - "metadata": {}, |
348 | | - "source": [ |
349 | | - "## [City Skyline]()\n", |
350 | | - "\n", |
351 | | - "In: array of buildings (tuples); buildings[i] = [left_i, right_i, height_i]\n", |
352 | | - "Out: the \"skyline\"; a list of \"key points\" (sorted by x coordinate). Each key point is left endpoint of a horizontal segment in the skyline. The last key point for a segment should have y==0. Any ground needs to be part of the contouring. There should be no consecutive heights in the skyline. \n", |
353 | | - "\n", |
354 | | - "Constraints:\n", |
355 | | - " - 1 to 10000 buildings\n", |
356 | | - " - Building left/right can be between 0 and int max; left is always left of right. \n", |
357 | | - " - Height is 1 up to int max\n", |
358 | | - " - Buildings are sorted by left i in nondecreasing order\n", |
359 | | - " \n", |
360 | | - "Edge cases\n", |
361 | | - " - 1 building; should return [(building_left, height), (building_right, 0)]\n", |
362 | | - " - Every building overlaps\n", |
363 | | - " - 1 building completely covers another\n", |
364 | | - "\n", |
365 | | - "Do we need to look at every building?\n", |
366 | | - " - Yes; suppose a case where every building is blocked out by the last one. \n", |
367 | | - "\n", |
368 | | - "Overlapping intervals? \n", |
369 | | - "\n", |
370 | | - "Skyline with \n", |
371 | | - "\n", |
372 | | - "We can probably D&C this:\n", |
373 | | - " - A skyline can be split into two and merged afterwards\n", |
374 | | - " - D&C on list of buildings\n", |
375 | | - " - base case: one building - key points listed above\n", |
376 | | - " - merge step: can we merge key points?\n", |
377 | | - " - How do we merge without having to n^2 compare all key points \n", |
378 | | - " - Mergesort merge starting from leftmost? \n", |
379 | | - "\n", |
380 | | - "What if we merge to \"multiheight buildings\"? \n", |
381 | | - "\n", |
382 | | - "Every building can start as two key points: (l, h), (r,0). We can convert them to these and then merge them. \n", |
383 | | - "\n", |
384 | | - "Critical points are merged in 3s. For points l,m,r where l.x <= m.x <= r.x:\n", |
385 | | - "- if l.h > m.h\n", |
386 | | - "\n", |
387 | | - "Two separate things here (might be able to do them concurrently):\n", |
388 | | - "- Merge buildings -> convert list of (l,r,h) to [(x,h),(x,h)....]\n", |
389 | | - " - nlogn \n", |
390 | | - " - starts with leftmost l and height; ends with rightmost r and 0. \n", |
391 | | - " - We can do this in nlogn time by binary searching the list (or bisecting) \n", |
392 | | - " - in the heights list, if l.h > r.h, area is obscured. if l.h < r.h, area open. Never l.h = r.h; not valid. \n", |
393 | | - "- Get key points\n", |
394 | | - " - Merged buildings have only one way of being drawn with critical points \n", |
395 | | - " \n", |
396 | | - " \n", |
397 | | - "How do we merge two buildings? \n", |
398 | | - "\n", |
399 | | - "If we merge a single building with one that has multiple heights, we potentially have to compare the single height to every height in the building (O(n)).\n", |
400 | | - " - If we use D&C, we do this log(n) times. \n", |
401 | | - " \n", |
402 | | - "D&C approach:\n", |
403 | | - " - Divide our list of buildings in half\n", |
404 | | - " - Base case: one building - return (l,h),(r,0)\n", |
405 | | - " - combine: each recursive case returns a list of possible key points, which then need to be merged. \n", |
406 | | - " - Do we need to store references to the buildings after returning key points? \n", |
407 | | - " - No: we only remove points that were already there when adding new points to the list \n", |
408 | | - " \n", |
409 | | - "How do we combine (l1, h1), (r1, 0), (l2, h2), (r2, 0)?\n", |
410 | | - "- lefts and rights either are separate, adjacent, overlapping, equal, or covering\n", |
411 | | - " - separate: l1 < r1 < l2 < r2\n", |
412 | | - " - Always: keep all\n", |
413 | | - " - adjacent: r1 == l2\n", |
414 | | - " - h1 == h2: (l1, h1), (r2, 0)\n", |
415 | | - " - h1 != h2: (l1, h1), (r2, 0) (r1, h2)\n", |
416 | | - " - overlapping: l1 <= l2 <= r1 <= r2 and not (l1 == l2 and r1==r2)\n", |
417 | | - " - h1 == h2: (l1, h1), (r2, 0)\n", |
418 | | - " - h1 != h2: above, and (r1,h2) if left is taller, else (l2, h2)\n", |
419 | | - " - equal: l1 == l2 and r1 == r2\n", |
420 | | - " - always: (l1, h1), (r2, 0)\n", |
421 | | - " - covering: l1 < l2 < r2 < r1 or l2 < l1 < r1 < r2\n", |
422 | | - " - eq height or inner smaller: (outer left, h) (outer right, 0)\n", |
423 | | - " - diff height and inner greater: (outer l, outer h), (inner l, inner h), (inner r, inner h), (outer r, 0) \n", |
424 | | - " \n", |
425 | | - "How do we combine two n-len lists of points?\n", |
426 | | - " - sorted insert of both, then reduce (might need to keep track of which points came from 1 vs 2, all points in 1 are fine as is)\n", |
427 | | - " - for any three points l,r,m:\n", |
428 | | - " - if l.h == m.h or m.h == r.h\n", |
429 | | - " - if l/m or m/r came from same list, done\n", |
430 | | - " - if l.h < m.h < r.h, done\n", |
431 | | - "\n", |
432 | | - "Can we do mergesort style merge for linear time?" |
433 | | - ] |
434 | | - }, |
435 | 345 | { |
436 | 346 | "cell_type": "code", |
437 | 347 | "execution_count": null, |
|
0 commit comments