Skip to content

Commit 6c7e71f

Browse files
committed
Annotate chapter 2
1 parent cf7291e commit 6c7e71f

File tree

11 files changed

+111
-66
lines changed

11 files changed

+111
-66
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> Existing Python solutions can be found [officially here](https://github.com/careercup/CtCI-6th-Edition-Python/tree/e6bc732588601d0a98e5b1bc44d83644b910978d) and [user-created here](https://github.com/w-hat/ctci-solutions)
44
5-
### Current progress
5+
## Current progress
66
| Nr. | Chapter | Done | Total | Ommited | Notes |
77
|:---: |:----------------------: |:----: |:-----: |:-------: | :-------: |
88
| 1 | [Array and String](chapter_1) | 9 | 9 | | | |
@@ -24,15 +24,15 @@
2424
| 17 | [Hard](chapter_17) | 26 | 26 | | |
2525

2626

27-
### Running the solutions
27+
## Running the solutions
2828

29-
For convenience, the project has a `setup.py` that specifies a package
30-
This can be installed locally in the python (virtual)environment by using
29+
For convenience, the project has a `setup.py` that specifies a package, for local path resolving.
30+
This can be installed locally in the python (virtual)environment by using:
3131
```bash
3232
pip install -e .
3333
```
3434

35-
Problems can be run by running the file, most should have a main method.
35+
Problems can be run by running the file, most should have a main method with some sample input, e.g. :
3636
```bash
3737
python p16_20.py
3838
```

chapter_2/linked_list_utils.py

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def link_list_of_list(arr) -> Node:
2020

2121

2222
def llol(arr):
23+
"""Shorthand for (make) linked-list of list
24+
"""
2325
return link_list_of_list(arr)
2426

2527

chapter_2/p2_1.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
from chapter_2.linked_list_utils import Node, llol
22

3+
# Method: Use a set
4+
# Time: O(n)
5+
# Space: O(n)
6+
7+
# Method (no buffer): Pick one, try to find in rest of linked list
8+
# Time: O(n^2)
9+
# Space: O(1)
10+
311

412
def remove_dups_ll(head: Node):
513
seen = set()
@@ -13,18 +21,18 @@ def remove_dups_ll(head: Node):
1321
head = head.next
1422

1523

16-
def remove_dups_nobuf(h: Node):
17-
rc = h
24+
def remove_dups_nobuf(head: Node):
25+
rc = head
1826
while rc:
1927
target = rc.val
2028
prev = rc
21-
restp = rc.next
22-
while restp:
23-
if restp.val == target:
24-
prev.next = restp.next
29+
rest_ptr = rc.next
30+
while rest_ptr:
31+
if rest_ptr.val == target:
32+
prev.next = rest_ptr.next
2533
else:
26-
prev = restp
27-
restp = restp.next
34+
prev = rest_ptr
35+
rest_ptr = rest_ptr.next
2836
rc = rc.next
2937

3038

chapter_2/p2_2.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
from chapter_2.linked_list_utils import *
22

3+
# Method: Leader and follower pointer, at k distance
4+
# Time: O(n)
5+
# Space: O(1)
36

4-
def k_to_last(k: int, h: Node):
5-
ldr = h
6-
folw = h
7-
d = -1
87

9-
while ldr:
10-
print(f"Ldr is {ldr} and folw {folw}")
11-
d += 1
12-
if d > k:
13-
folw = folw.next
14-
ldr = ldr.next
8+
def k_to_last(k: int, head: Node):
9+
leader_ptr = head
10+
follower_ptr = head
11+
distance = -1
1512

16-
if d < k:
17-
raise Exception(f"Input too short for distance {d}")
13+
while leader_ptr:
14+
print(f"Leader is {leader_ptr} "
15+
f"and follower {follower_ptr},"
16+
f" at distance {distance}")
17+
distance += 1
18+
if distance > k:
19+
follower_ptr = follower_ptr.next
20+
leader_ptr = leader_ptr.next
1821

19-
return folw.val
22+
if distance < k:
23+
raise Exception(f"Input too short for distance {distance}")
24+
25+
return follower_ptr.val
2026

2127

2228
if __name__ == "__main__":

chapter_2/p2_3.py

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from chapter_2.linked_list_utils import llol, Node
22

3+
# Method: Identity theft
4+
# Time: O(1)
5+
# Space: O(1)
6+
37

48
def remove_mid(mid_node: Node):
59
victim = mid_node.next

chapter_2/p2_4.py

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from chapter_2.linked_list_utils import llol, Node
22

3+
# Method: Construct 2 other lists
4+
# Time: O(n)
5+
# Space: O(1)
6+
37

48
def part_around(x: int, head: Node):
59
low_head = None

chapter_2/p2_5.py

+10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
from chapter_2.linked_list_utils import Node, lllen, llol
22

3+
# Backward oder (head at least significant)
4+
# Method: Digit by digit, with carry
5+
# Time: O(n)
6+
# Space: O(n) (Constant if you overwrite one of the inputs)
7+
8+
# Forward order
9+
# Method: Pad to len, recurse down
10+
# Time: O(n)
11+
# Space: O(n)
12+
313

414
def sum_ll(tl1: Node, tl2: Node):
515
nl = None

chapter_2/p2_6.py

+25-21
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,42 @@
11
from chapter_2.linked_list_utils import Node, llol
22

3+
# Method: Slow/Fast pointer, push to stack second half and check
4+
# Time: O(n)
5+
# Space: O(n)
36

4-
def check_ll_palindrome(h: Node):
5-
sl_len = -1
6-
fst_len = -1
77

8-
if not h:
8+
def check_ll_palindrome(head: Node):
9+
slow_len = -1
10+
fast_len = -1
11+
12+
if not head:
913
return True
1014

11-
slp = h
12-
fstp = h
15+
slow_ptr = head
16+
fast_ptr = head
1317
stack = []
14-
while fstp:
15-
sl_len += 1
16-
fst_len += 2
17-
stack.append(slp.val)
18+
while fast_ptr:
19+
slow_len += 1
20+
fast_len += 2
21+
stack.append(slow_ptr.val)
1822

19-
slp = slp.next
20-
fstp = fstp.next
23+
slow_ptr = slow_ptr.next
24+
fast_ptr = fast_ptr.next
2125

22-
if fstp:
23-
fstp = fstp.next
24-
if not fstp:
25-
fst_len += 1
26+
if fast_ptr:
27+
fast_ptr = fast_ptr.next
28+
if not fast_ptr:
29+
fast_len += 1
2630

27-
if fst_len > 0 and fst_len % 2:
31+
if fast_len > 0 and fast_len % 2:
2832
stack.pop()
2933

30-
print(f"Stack is {stack}, slp is {slp}")
34+
print(f"Stack is {stack}, slp is {slow_ptr}")
3135

32-
while slp:
33-
if slp.val != stack.pop():
36+
while slow_ptr:
37+
if slow_ptr.val != stack.pop():
3438
return False
35-
slp = slp.next
39+
slow_ptr = slow_ptr.next
3640

3741
return not stack
3842

chapter_2/p2_7.py

+17-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
from chapter_2.linked_list_utils import Node, link_list_of_list, lllen, llol
22

3+
# Method: Find total lenght, walk together until meet
4+
# Time: O(n)
5+
# Space: O(1)
6+
37

48
def get_intersecting_node(h1: Node, h2: Node):
5-
ll1 = lllen(h1)
6-
ll2 = lllen(h2)
9+
len_ll1 = lllen(h1)
10+
len_ll2 = lllen(h2)
711

812
if get_last_of_ll(h1) != get_last_of_ll(h2):
913
return None
1014

11-
if ll1 > ll2:
12-
sl = h2
13-
bl = h1
15+
if len_ll1 > len_ll2:
16+
short_ll = h2
17+
longer_ll = h1
1418
else:
15-
sl = h1
16-
bl = h2
17-
18-
bl = adjust(bl, abs(ll1 - ll2))
19-
while bl != sl:
20-
bl = bl.next
21-
sl = sl.next
22-
return bl.val
19+
short_ll = h1
20+
longer_ll = h2
21+
22+
longer_ll = adjust(longer_ll, abs(len_ll1 - len_ll2))
23+
while longer_ll != short_ll:
24+
longer_ll = longer_ll.next
25+
short_ll = short_ll.next
26+
return longer_ll.val
2327

2428

2529
def adjust(head: Node, jumps):

chapter_2/p2_8.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from chapter_2.linked_list_utils import Node
22

3+
# Method: Fast/Slow pointer to meeting, restart pointer at beginning
4+
# Time: O(n)
5+
# Space: O(1)
36

47
def get_first_loop_elem(h: Node):
58
if not h.next:

chapter_2/readme.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ The complexity table is for a quick lookup, more details in the actual file (e.g
44

55
| Nr. | Title | Solution | Time | Space | Notes |
66
|:---: |:-----: |:--------: |:----: |:-----: |:-----: |
7-
| 2.1 | Remove dups | [Python](./p2_1.py) | O(n) | O(n) | |
8-
| 2.2 | Return Kth to last | [Python](./p2_2.py) | O(n*log(n)) | O(n) | |
9-
| 2.3 | Delete Middle Node | [Python](./p2_3.py) | O(n) | O(1) | |
7+
| 2.1 | Remove dups | [Python](./p2_1.py) | O(n^2) | O(1) | |
8+
| 2.2 | Return Kth to last | [Python](./p2_2.py) | O(n)) | O(1) | |
9+
| 2.3 | Delete Middle Node | [Python](./p2_3.py) | O(1) | O(1) | |
1010
| 2.4 | Partition | [Python](./p2_4py) | O(n) | O(1) | |
11-
| 2.5 | Sum Lists | [Python](./p2_5.py) | O(min(n,m)) | O(1) | |
11+
| 2.5 | Sum Lists | [Python](./p2_5.py) | O(n) | O(n) | |
1212
| 2.6 | Palindrome | [Python](./p2_6.py) | O(n) | O(n) | |
13-
| 2.7 | Intersection | [Python](./p2_7.py) | O(n*m) | O(1) | |
14-
| 2.8 | Loop Detection | [Python](./p2_8.py) | O(n*m) | O(1) | |
13+
| 2.7 | Intersection | [Python](./p2_7.py) | O(n) | O(1) | |
14+
| 2.8 | Loop Detection | [Python](./p2_8.py) | O(n) | O(1) | |

0 commit comments

Comments
 (0)