Skip to content

Commit 8b245bb

Browse files
committed
add divide and conquer changes
1 parent 91bd2f0 commit 8b245bb

File tree

4 files changed

+196
-92
lines changed

4 files changed

+196
-92
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Data Structure - Graphs"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": 4,
13+
"metadata": {},
14+
"outputs": [
15+
{
16+
"name": "stdout",
17+
"output_type": "stream",
18+
"text": [
19+
"1 [2, 3]\n",
20+
"2 [4, 5]\n",
21+
"4 [8, 9]\n",
22+
"8 []\n",
23+
"9 []\n",
24+
"5 [10]\n",
25+
"10 []\n",
26+
"3 [6, 7]\n",
27+
"6 [10]\n",
28+
"7 [11]\n",
29+
"11 []\n"
30+
]
31+
}
32+
],
33+
"source": [
34+
"from typing import Union, List\n",
35+
"\n",
36+
"class GraphNode:\n",
37+
" def __init__(self, value: int = None, children: Union[List, None] = None):\n",
38+
" self.children = children if children else []\n",
39+
" self.value = value\n",
40+
"\n",
41+
"\n",
42+
"nodes = {val: GraphNode(value=val) for val in range(1,12)}\n",
43+
"nodes[1].children += [nodes[2], nodes[3]]\n",
44+
"nodes[2].children += [nodes[4], nodes[5]]\n",
45+
"nodes[3].children += [nodes[6], nodes[7]]\n",
46+
"nodes[4].children += [nodes[8], nodes[9]]\n",
47+
"nodes[5].children += [nodes[10]]\n",
48+
"nodes[6].children += [nodes[10]]\n",
49+
"nodes[7].children += [nodes[11]]\n",
50+
"root = nodes[1]\n",
51+
"\n",
52+
"def create_adj_list(root: GraphNode, adj_list: dict):\n",
53+
" # Assume cycles may exist\n",
54+
" if root in adj_list: return \n",
55+
" adj_list[root] = set()\n",
56+
" \n",
57+
" for child in root.children:\n",
58+
" # set allows for checking if an edge exists in O(1) \n",
59+
" adj_list[root].add(child) \n",
60+
" create_adj_list(child, adj_list) if child not in adj_list else None\n",
61+
"\n",
62+
"adj_list = {}\n",
63+
"create_adj_list(root, adj_list)\n",
64+
"for node in adj_list:\n",
65+
" print(node.value, [child.value for child in node.children])"
66+
]
67+
},
68+
{
69+
"cell_type": "code",
70+
"execution_count": null,
71+
"metadata": {},
72+
"outputs": [],
73+
"source": []
74+
}
75+
],
76+
"metadata": {
77+
"kernelspec": {
78+
"display_name": "Python 3",
79+
"language": "python",
80+
"name": "python3"
81+
},
82+
"language_info": {
83+
"codemirror_mode": {
84+
"name": "ipython",
85+
"version": 3
86+
},
87+
"file_extension": ".py",
88+
"mimetype": "text/x-python",
89+
"name": "python",
90+
"nbconvert_exporter": "python",
91+
"pygments_lexer": "ipython3",
92+
"version": "3.8.5"
93+
}
94+
},
95+
"nbformat": 4,
96+
"nbformat_minor": 4
97+
}

implementations/Technique - Divide and Conquer.ipynb

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -342,96 +342,6 @@
342342
" assert actual == expected, f\"{matrix,val}: {expected} != {actual}\""
343343
]
344344
},
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-
},
435345
{
436346
"cell_type": "code",
437347
"execution_count": null,
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Technique - Stacks \n"
8+
]
9+
},
10+
{
11+
"cell_type": "markdown",
12+
"metadata": {},
13+
"source": [
14+
"- Can we use recursion any time we use stacks?\n",
15+
"- Can we use stacks to preserve ordering?"
16+
]
17+
},
18+
{
19+
"cell_type": "markdown",
20+
"metadata": {},
21+
"source": [
22+
"## [Daily Temperatures](https://leetcode.com/problems/daily-temperatures/)"
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 9,
28+
"metadata": {},
29+
"outputs": [],
30+
"source": [
31+
"from typing import List\n",
32+
"\n",
33+
"class Solution:\n",
34+
" def dailyTemperatures(self, T: List[int]) -> List[int]:\n",
35+
" solution = []\n",
36+
" stack = []\n",
37+
" for i in range(len(T)-1, -1, -1):\n",
38+
" curr_temp = T[i]\n",
39+
" while stack and stack[-1][0] <= curr_temp: stack.pop()\n",
40+
" solution.append(0 if not stack else stack[-1][1]-i)\n",
41+
" stack.append((curr_temp,i))\n",
42+
" return solution[::-1]\n",
43+
"\n",
44+
"s = Solution()\n",
45+
"cases = [\n",
46+
" ([73, 74, 75, 71, 69, 72, 76, 73], [1, 1, 4, 2, 1, 1, 0, 0]),\n",
47+
" ([89,62,70,58,47,47,46,76,100,70], [8,1,5,4,3,2,1,1,0,0])\n",
48+
"]\n",
49+
"for temps, expected in cases:\n",
50+
" actual = s.dailyTemperatures(temps)\n",
51+
" assert actual == expected, f\"{temps}: {expected} != {actual}\""
52+
]
53+
},
54+
{
55+
"cell_type": "markdown",
56+
"metadata": {},
57+
"source": [
58+
"## [Basic Calculator](https://leetcode.com/problems/basic-calculator/)"
59+
]
60+
}
61+
],
62+
"metadata": {
63+
"kernelspec": {
64+
"display_name": "Python 3",
65+
"language": "python",
66+
"name": "python3"
67+
},
68+
"language_info": {
69+
"codemirror_mode": {
70+
"name": "ipython",
71+
"version": 3
72+
},
73+
"file_extension": ".py",
74+
"mimetype": "text/x-python",
75+
"name": "python",
76+
"nbconvert_exporter": "python",
77+
"pygments_lexer": "ipython3",
78+
"version": "3.8.5"
79+
}
80+
},
81+
"nbformat": 4,
82+
"nbformat_minor": 4
83+
}

implementations/Technique - Topological Sorting.ipynb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@
6565
"When in doubt:\n",
6666
"- Assume nodes may have unbounded children\n",
6767
"- Assume cycles may exist\n",
68-
"- Don't modify the input graph; generate an adjacency list or collection of nodes and modify that.\n",
69-
"- Rule out the possibility of unreachable nodes before proceeding.\n",
68+
"- If performance isn't totally critical, don't modify the input graph; generate an adjacency list or collection of nodes and modify that.\n",
69+
"- Rule out the possibility of unreachable nodes (either make sure you have a reference to every node, or that all nodes will be reachable from whatever subset you're given).\n",
7070
"\n",
7171
"\n",
7272
"The basic DFS implementation for topological ordering requires two functions:\n",
@@ -276,6 +276,20 @@
276276
" print(s.findOrder(n_courses, prereqs))"
277277
]
278278
},
279+
{
280+
"cell_type": "markdown",
281+
"metadata": {},
282+
"source": [
283+
"## Example: [Graph Valid Tree](https://leetcode.com/problems/graph-valid-tree/)"
284+
]
285+
},
286+
{
287+
"cell_type": "code",
288+
"execution_count": null,
289+
"metadata": {},
290+
"outputs": [],
291+
"source": []
292+
},
279293
{
280294
"cell_type": "markdown",
281295
"metadata": {},

0 commit comments

Comments
 (0)