1
+ import copy
1
2
from typing import List , Any , Tuple
2
3
3
4
@@ -27,7 +28,7 @@ def __init__(self, items: List[Any] = None):
27
28
if items is not None :
28
29
node = Node (data = items [0 ])
29
30
self .head = node
30
- self .add_last (items [1 :])
31
+ self .add_items (items [1 :])
31
32
32
33
def __repr__ (self ):
33
34
items = self .tolist ()
@@ -43,11 +44,9 @@ def __iter__(self):
43
44
node = node .next
44
45
45
46
def __len__ (self ):
46
- i = 0
47
- for node in self :
48
- i += 1
47
+ size , _ = self .size_and_tail ()
49
48
50
- return i
49
+ return size
51
50
52
51
def __eq__ (self , other ):
53
52
if not isinstance (other , LinkedList ):
@@ -79,7 +78,12 @@ def tolist(self):
79
78
def tostring (self ):
80
79
return '' .join (map (str , self .tolist ()))
81
80
82
- def add_last (self , items : List [Any ]):
81
+ def add_node (self , node : Node ):
82
+ """Inserts a node at the end of the linked-list."""
83
+ last_node = self .get_last ()
84
+ last_node .next = node
85
+
86
+ def add_items (self , items : List [Any ]):
83
87
"""Inserts list of items at the end of the linked list."""
84
88
tail = self .head
85
89
@@ -100,21 +104,53 @@ def get_node(self, data):
100
104
101
105
return node
102
106
107
+ def get_last (self ):
108
+ """Returns last node."""
109
+ node = None
110
+ for n in self :
111
+ node = n
112
+
113
+ return node
114
+
115
+ def at (self , idx ):
116
+ """Returns node at index idx."""
117
+ i = 0
118
+ for node in self :
119
+ if i == idx :
120
+ return node
121
+
122
+ i += 1
123
+
124
+ raise ValueError ("index {} out of bounds for list: {}!" .format (idx , self .tolist ()))
125
+
103
126
def reverse (self ):
104
- """Returns the linked listed reversed."""
105
- tail = None
127
+ """Reverses the linked list in-place.
106
128
107
- node = self . head
108
- while node is not None :
109
- n = Node ( data = node . data )
110
- n . next = tail
111
- tail = n
112
- node = node . next
129
+ Complexity:
130
+ - Time: O(N).
131
+ - Space: O(1 )
132
+ """
133
+ _prev = None
134
+ _current = self . head
113
135
114
- llist = LinkedList ()
115
- llist .head = tail
136
+ while _current is not None :
137
+ _next = _current .next
138
+ _current .next = _prev
139
+ _prev = _current
140
+ _current = _next
116
141
117
- return llist
142
+ self .head = _prev
143
+
144
+ def size_and_tail (self ):
145
+ """Returns the size and tail of linked-list."""
146
+ i = 0
147
+ node = None
148
+
149
+ for n in self :
150
+ node = n
151
+ i += 1
152
+
153
+ return i , node
118
154
119
155
120
156
def remove_duplicates (llist : LinkedList ) -> None :
@@ -272,7 +308,7 @@ def sum(l1: LinkedList, l2: LinkedList) -> LinkedList:
272
308
return LinkedList (l3_numbers [::- 1 ])
273
309
274
310
275
- def is_palindrome (llist : LinkedList , method = 'reverse' ) -> bool :
311
+ def is_palindrome (llist : LinkedList , method : str = 'reverse' ) -> bool :
276
312
"""Checks if the items in a linked-list form a palindrome.
277
313
278
314
Complexity:
@@ -285,7 +321,10 @@ def is_palindrome(llist: LinkedList, method='reverse') -> bool:
285
321
raise ValueError ("Method {} not valid. Choose from {}" .format (method , METHODS ))
286
322
287
323
if method == 'reverse' :
288
- return llist == llist .reverse ()
324
+ llist_copy = copy .deepcopy (llist )
325
+ llist .reverse ()
326
+
327
+ return llist_copy == llist
289
328
290
329
elif method == 'iterative' :
291
330
stack = []
@@ -326,3 +365,36 @@ def recursive(head: Node, length: int):
326
365
_ , res = recursive (llist .head , len (llist ))
327
366
328
367
return res
368
+
369
+
370
+ def intersection (l1 : LinkedList , l2 : LinkedList ):
371
+ """Finds an intersecting node between l2 and l2 linked-lists."""
372
+
373
+ l1_len , l1_tail = l1 .size_and_tail ()
374
+ l2_len , l2_tail = l2 .size_and_tail ()
375
+
376
+ if l1_len == 0 or l2_len == 0 :
377
+ return False , None
378
+
379
+ if l1_tail is not l2_tail :
380
+ return False , None
381
+
382
+ len_diff = abs (l1_len - l2_len )
383
+
384
+ p1 = l1 .head
385
+ p2 = l2 .head
386
+
387
+ if l1_len > l2_len :
388
+ p1 = l1 .at (len_diff )
389
+
390
+ if l2_len > l1_len :
391
+ p2 = l2 .at (len_diff )
392
+
393
+ while p1 is not None :
394
+ if p1 is p2 :
395
+ break
396
+
397
+ p1 = p1 .next
398
+ p2 = p2 .next
399
+
400
+ return True , p1
0 commit comments