"""You are given two non-empty linked lists representingtwo non-negative integers. The digits are stored in reverse orderand each of their nodes contain a single digit.Add the two numbers and return it as a linked list.You may assume the two numbers do not contain any leading zero,except the number 0 itself.Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)Output: 7 -> 0 -> 8"""import unittestclassNode:def__init__(self,x): self.val = x self.next =Nonedefadd_two_numbers(left: Node,right: Node) -> Node: head =Node(0) current = headsum=0while left or right:print("adding: ", left.val, right.val)sum//=10if left:sum+= left.val left = left.nextif right:sum+= right.val right = right.next current.next =Node(sum%10) current = current.nextifsum//10==1: current.next =Node(1)return head.nextdefconvert_to_list(number:int) -> Node:""" converts a positive integer into a (reversed) linked list. for example: give 112 result 2 -> 1 -> 1 """if number >=0: head =Node(0) current = head remainder = number %10 quotient = number //10while quotient !=0: current.next =Node(remainder) current = current.next remainder = quotient %10 quotient //=10 current.next =Node(remainder)return head.nextelse:print("number must be positive!")defconvert_to_str(l: Node) ->str:""" converts the non-negative number list into a string. """ result =""while l: result +=str(l.val) l = l.nextreturn resultclassTestSuite(unittest.TestCase):""" testsuite for the linked list structure and the adding function, above. """deftest_convert_to_str(self): number1 =Node(2) number1.next =Node(4) number1.next.next =Node(3) self.assertEqual("243", convert_to_str(number1))deftest_add_two_numbers(self):# 1. test case number1 =Node(2) number1.next =Node(4) number1.next.next =Node(3) number2 =Node(5) number2.next =Node(6) number2.next.next =Node(4) result =convert_to_str(add_two_numbers(number1, number2)) self.assertEqual("708", result)# 2. test case number3 =Node(1) number3.next =Node(1) number3.next.next =Node(9) number4 =Node(1) number4.next =Node(0) number4.next.next =Node(1) result =convert_to_str(add_two_numbers(number3, number4)) self.assertEqual("2101", result)# 3. test case number5 =Node(1) number6 =Node(0) result =convert_to_str(add_two_numbers(number5, number6)) self.assertEqual("1", result)# 4. test case number7 =Node(9) number7.next =Node(1) number7.next.next =Node(1) number8 =Node(1) number8.next =Node(0) number8.next.next =Node(1) result =convert_to_str(add_two_numbers(number7, number8)) self.assertEqual("022", result)deftest_convert_to_list(self): result =convert_to_str(convert_to_list(112)) self.assertEqual("211", result)if__name__=="__main__": unittest.main()"""A linked list is given such that each node contains an additional randompointer which could point to any node in the list or null.Return a deep copy of the list."""from collections import defaultdictclassRandomListNode(object):def__init__(self,label): self.label = label self.next =None self.random =Nonedefcopy_random_pointer_v1(head):""" :type head: RandomListNode :rtype: RandomListNode """ dic =dict() m = n = headwhile m: dic[m]=RandomListNode(m.label) m = m.nextwhile n: dic[n].next = dic.get(n.next) dic[n].random = dic.get(n.random) n = n.nextreturn dic.get(head)# O(n)defcopy_random_pointer_v2(head):""" :type head: RandomListNode :rtype: RandomListNode """ copy =defaultdict(lambda: RandomListNode(0)) copy[None]=None node = headwhile node: copy[node].label = node.label copy[node].next = copy[node.next] copy[node].random = copy[node.random] node = node.nextreturn copy[head]"""Write a function to delete a node (except the tail)in a singly linked list, given only access to that node.Supposed the linked list is 1 -> 2 -> 3 -> 4 andyou are given the third node with value 3,the linked list should become 1 -> 2 -> 4 after calling your function."""import unittestclassNode:def__init__(self,x): self.val = x self.next =Nonedefdelete_node(node):if node isNoneor node.next isNone:raiseValueError node.val = node.next.val node.next = node.next.nextclassTestSuite(unittest.TestCase):deftest_delete_node(self):# make linkedlist 1 -> 2 -> 3 -> 4 head =Node(1) curr = headfor i inrange(2, 6): curr.next =Node(i) curr = curr.next# node3 = 3 node3 = head.next.next# after delete_node => 1 -> 2 -> 4delete_node(node3) curr = head self.assertEqual(1, curr.val) curr = curr.next self.assertEqual(2, curr.val) curr = curr.next self.assertEqual(4, curr.val) curr = curr.next self.assertEqual(5, curr.val) tail = curr self.assertIsNone(tail.next) self.assertRaises(ValueError, delete_node, tail) self.assertRaises(ValueError, delete_node, tail.next)if__name__=="__main__": unittest.main()""" Given a linked list, find the first node of a cycle in it. 1 -> 2 -> 3 -> 4 -> 5 -> 1 => 1 A -> B -> C -> D -> E -> C => C Note: The solution is a direct implementation Floyd's cycle-finding algorithm (Floyd's Tortoise and Hare)."""import unittestclassNode:def__init__(self,x): self.val = x self.next =Nonedeffirst_cyclic_node(head):""" :type head: Node :rtype: Node """ runner = walker = headwhile runner and runner.next: runner = runner.next.next walker = walker.nextif runner is walker:breakif runner isNoneor runner.next isNone:returnNone walker = headwhile runner isnot walker: runner, walker = runner.next, walker.nextreturn runnerclassTestSuite(unittest.TestCase):deftest_first_cyclic_node(self):# create linked list => A -> B -> C -> D -> E -> C head =Node("A") head.next =Node("B") curr = head.next cyclic_node =Node("C") curr.next = cyclic_node curr = curr.next curr.next =Node("D") curr = curr.next curr.next =Node("E") curr = curr.next curr.next = cyclic_node self.assertEqual("C", first_cyclic_node(head).val)if__name__=="__main__": unittest.main()from.reverse import*from.is_sorted import*from.remove_range import*from.swap_in_pairs import*from.rotate_list import*from.is_cyclic import*from.merge_two_list import*from.is_palindrome import*from.copy_random_pointer import*""" This function takes two lists and returns the node they have in common, if any. In this example: 1 -> 3 -> 5\ 7 -> 9 -> 11 / 2 -> 4 -> 6 ...we would return 7. Note that the node itself is the unique identifier, not the value of the node. """import unittestclassNode(object):def__init__(self,val=None): self.val = val self.next =Nonedefintersection(h1,h2): count =0 flag =None h1_orig = h1 h2_orig = h2while h1 or h2: count +=1ifnot flag and (h1.next isNoneor h2.next isNone):# We hit the end of one of the lists, set a flag for this flag = (count, h1.next, h2.next)if h1: h1 = h1.nextif h2: h2 = h2.next long_len = count # Mark the length of the longer of the two lists short_len = flag[0]if flag[1]isNone: shorter = h1_orig longer = h2_origelif flag[2]isNone: shorter = h2_orig longer = h1_origwhile longer and shorter:while long_len > short_len:# force the longer of the two lists to "catch up" longer = longer.next long_len -=1if longer == shorter:# The nodes match, return the nodereturn longerelse: longer = longer.next shorter = shorter.nextreturnNoneclassTestSuite(unittest.TestCase):deftest_intersection(self):# create linked list as:# 1 -> 3 -> 5# \# 7 -> 9 -> 11# /# 2 -> 4 -> 6 a1 =Node(1) b1 =Node(3) c1 =Node(5) d =Node(7) a2 =Node(2) b2 =Node(4) c2 =Node(6) e =Node(9) f =Node(11) a1.next = b1 b1.next = c1 c1.next = d a2.next = b2 b2.next = c2 c2.next = d d.next = e e.next = f self.assertEqual(7, intersection(a1, a2).val)if__name__=="__main__": unittest.main()"""Given a linked list, determine if it has a cycle in it.Follow up:Can you solve it without using extra space?"""classNode:def__init__(self,x): self.val = x self.next =Nonedefis_cyclic(head):""" :type head: Node :rtype: bool """ifnot head:returnFalse runner = head walker = headwhile runner.next and runner.next.next: runner = runner.next.next walker = walker.nextif runner == walker:returnTruereturnFalsedefis_palindrome(head):ifnot head:returnTrue# split the list to two parts fast, slow = head.next, headwhile fast and fast.next: fast = fast.next.next slow = slow.next second = slow.next slow.next =None# Don't forget here! But forget still works!# reverse the second part node =Nonewhile second: nxt = second.next second.next = node node = second second = nxt# compare two parts# second part has the same or one less nodewhile node:if node.val != head.val:returnFalse node = node.next head = head.nextreturnTruedefis_palindrome_stack(head):ifnot head ornot head.next:returnTrue# 1. Get the midpoint (slow) slow = fast = cur = headwhile fast and fast.next: fast, slow = fast.next.next, slow.next# 2. Push the second half into the stack stack = [slow.val]while slow.next: slow = slow.next stack.append(slow.val)# 3. Comparisonwhile stack:if stack.pop()!= cur.val:returnFalse cur = cur.nextreturnTruedefis_palindrome_dict(head):""" This function builds up a dictionary where the keys are the values of the list, and the values are the positions at which these values occur in the list. We then iterate over the dict and if there is more than one key with an odd number of occurrences, bail out and return False. Otherwise, we want to ensure that the positions of occurrence sum to the value of the length of the list - 1, working from the outside of the list inward. For example: Input: 1 -> 1 -> 2 -> 3 -> 2 -> 1 -> 1 d = {1: [0,1,5,6], 2: [2,4], 3: [3]} '3' is the middle outlier, 2+4=6, 0+6=6 and 5+1=6 so we have a palindrome. """ifnot head ornot head.next:returnTrue d ={} pos =0while head:if head.val in d.keys(): d[head.val].append(pos)else: d[head.val]= [pos] head = head.next pos +=1 checksum = pos -1 middle =0for v in d.values():iflen(v)%2!=0: middle +=1else: step =0for i inrange(0, len(v)):if v[i]+ v[len(v)-1- step]!= checksum:returnFalse step +=1if middle >1:returnFalsereturnTrue"""Given a linked list, is_sort function returns true if the list is in sorted(increasing) order and return false otherwise. An empty list is consideredto be sorted.For example:Null :List is sorted1 2 3 4 :List is sorted1 2 -1 3 :List is not sorted"""defis_sorted(head):ifnot head:returnTrue current = headwhile current.next:if current.val > current.next.val:returnFalse current = current.nextreturnTrueclassNode:def__init__(self,val=None): self.val = val self.next =Nonedefkth_to_last_eval(head,k):""" This is a suboptimal, hacky method using eval(), which is not safe for user input. We guard against danger by ensuring k in an int """ifnotisinstance(k, int)ornot head.val:returnFalse nexts =".".join(["next"for n inrange(1, k +1)]) seeker =str(".".join(["head", nexts]))while head:ifeval(seeker)isNone:return headelse: head = head.nextreturnFalsedefkth_to_last_dict(head,k):""" This is a brute force method where we keep a dict the size of the list Then we check it for the value we need. If the key is not in the dict, our and statement will short circuit and return False """ifnot (head and k >-1):returnFalse d =dict() count =0while head: d[count]= head head = head.next count +=1returnlen(d)- k in d and d[len(d)- k]defkth_to_last(head,k):""" This is an optimal method using iteration. We move p1 k steps ahead into the list. Then we move p1 and p2 together until p1 hits the end. """ifnot (head or k >-1):returnFalse p1 = head p2 = headfor i inrange(1, k +1):if p1 isNone:# Went too far, k is not validraiseIndexError p1 = p1.nextwhile p1: p1 = p1.next p2 = p2.nextreturn p2defprint_linked_list(head): string =""while head.next: string += head.val +" -> " head = head.next string += head.valprint(string)deftest():# def make_test_li# A A B C D C F G a1 =Node("A") a2 =Node("A") b =Node("B") c1 =Node("C") d =Node("D") c2 =Node("C") f =Node("F") g =Node("G") a1.next = a2 a2.next = b b.next = c1 c1.next = d d.next = c2 c2.next = f f.next = gprint_linked_list(a1)# test kth_to_last_eval kth =kth_to_last_eval(a1, 4)try:assert kth.val =="D"exceptAssertionErroras e: e.args += ("Expecting D, got %s"% kth.val,)raise# test kth_to_last_dict kth =kth_to_last_dict(a1, 4)try:assert kth.val =="D"exceptAssertionErroras e: e.args += ("Expecting D, got %s"% kth.val,)raise# test kth_to_last kth =kth_to_last(a1, 4)try:assert kth.val =="D"exceptAssertionErroras e: e.args += ("Expecting D, got %s"% kth.val,)raiseprint("all passed.")if__name__=="__main__":test()# Pros# Linked Lists have constant-time insertions and deletions in any position,# in comparison, arrays require O(n) time to do the same thing.# Linked lists can continue to expand without having to specify# their size ahead of time (remember our lectures on Array sizing# from the Array Sequence section of the course!)# Cons# To access an element in a linked list, you need to take O(k) time# to go from the head of the list to the kth element.# In contrast, arrays have constant time operations to access# elements in an array.classDoublyLinkedListNode(object):def__init__(self,value): self.value = value self.next =None self.prev =NoneclassSinglyLinkedListNode(object):def__init__(self,value): self.value = value self.next =None"""Merge two sorted linked lists and return it as a new list. The new list shouldbe made by splicing together the nodes of the first two lists.For example:Input: 1->2->4, 1->3->4Output: 1->1->2->3->4->4"""classNode:def__init__(self,x): self.val = x self.next =Nonedefmerge_two_list(l1,l2): ret = cur =Node(0)while l1 and l2:if l1.val < l2.val: cur.next = l1 l1 = l1.nextelse: cur.next = l2 l2 = l2.next cur = cur.next cur.next = l1 or l2return ret.next# recursivelydefmerge_two_list_recur(l1,l2):ifnot l1 ornot l2:return l1 or l2if l1.val < l2.val: l1.next =merge_two_list_recur(l1.next, l2)return l1else: l2.next =merge_two_list_recur(l1, l2.next)return l2"""Write code to partition a linked list around a value x, such that all nodes lessthan x come before all nodes greater than or equal to x. If x is containedwithin the list, the values of x only need to be after the elements less than x.The partition element x can appear anywhere in the "right partition";it does not need to appear between the left and right partitions.3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 [partition=5]3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8We assume the values of all linked list nodes are int and that x in an int."""classNode:def__init__(self,val=None): self.val =int(val) self.next =Nonedefprint_linked_list(head): string =""while head.next: string +=str(head.val)+" -> " head = head.next string +=str(head.val)print(string)defpartition(head,x): left =None right =None prev =None current = headwhile current:ifint(current.val)>= x:ifnot right: right = currentelse:ifnot left: left = currentelse: prev.next = current.next left.next = current left = current left.next = rightif prev and prev.next isNone:break# cache previous value in case it needs to be pointed elsewhere prev = current current = current.nextdeftest(): a =Node("3") b =Node("5") c =Node("8") d =Node("5") e =Node("10") f =Node("2") g =Node("1") a.next = b b.next = c c.next = d d.next = e e.next = f f.next = gprint_linked_list(a)partition(a, 5)print_linked_list(a)if__name__=="__main__":test()classNode:def__init__(self,val=None): self.val = val self.next =Nonedefremove_dups(head):""" Time Complexity: O(N) Space Complexity: O(N) """ hashset =set() prev =Node()while head:if head.val in hashset: prev.next = head.nextelse: hashset.add(head.val) prev = head head = head.nextdefremove_dups_wothout_set(head):""" Time Complexity: O(N^2) Space Complexity: O(1) """ current = headwhile current: runner = currentwhile runner.next:if runner.next.val == current.val: runner.next = runner.next.nextelse: runner = runner.next current = current.nextdefprint_linked_list(head): string =""while head.next: string += head.val +" -> " head = head.next string += head.valprint(string)# A A B C D C F Ga1 =Node("A")a2 =Node("A")b =Node("B")c1 =Node("C")d =Node("D")c2 =Node("C")f =Node("F")g =Node("G")a1.next = a2a2.next = bb.next = c1c1.next = dd.next = c2c2.next = ff.next = gremove_dups(a1)print_linked_list(a1)remove_dups_wothout_set(a1)print_linked_list(a1)"""Given a linked list, remove_range function accepts a starting and ending indexas parameters and removes the elements at those indexes (inclusive) from the listFor example:List: [8, 13, 17, 4, 9, 12, 98, 41, 7, 23, 0, 92]remove_range(list, 3, 8);List becomes: [8, 13, 17, 23, 0, 92]legal range of the list (0 < start index < end index < size of list)."""defremove_range(head,start,end):assert start <= end# Case: remove node at headif start ==0:for i inrange(0, end +1):if head !=None: head = head.nextelse: current = head# Move pointer to start positionfor i inrange(0, start -1): current = current.next# Remove data until the endfor i inrange(0, end - start +1):if current !=Noneand current.next !=None: current.next = current.next.nextreturn head"""Reverse a singly linked list. For example:1 --> 2 --> 3 --> 4After reverse:4 --> 3 --> 2 --> 1"""## Iterative solution# T(n)- O(n)#defreverse_list(head):""" :type head: ListNode :rtype: ListNode """ifnot head ornot head.next:return head prev =Nonewhile head: current = head head = head.next current.next = prev prev = currentreturn prev## Recursive solution# T(n)- O(n)#defreverse_list_recursive(head):""" :type head: ListNode :rtype: ListNode """if head isNoneor head.next isNone:return head p = head.next head.next =None revrest =reverse_list_recursive(p) p.next = headreturn revrest"""Given a list, rotate the list to the right by k places,where k is non-negative.For example:Given 1->2->3->4->5->NULL and k = 2,return 4->5->1->2->3->NULL."""# Definition for singly-linked list.# class ListNode(object):# def __init__(self, x):# self.val = x# self.next = Nonedefrotate_right(head,k):""" :type head: ListNode :type k: int :rtype: ListNode """ifnot head ornot head.next:return head current = head length =1# count length of the listwhile current.next: current = current.next length +=1# make it circular current.next = head k = k % length# rotate until length-kfor i inrange(length - k): current = current.next head = current.next current.next =Nonereturn head"""Given a linked list, swap every two adjacent nodesand return its head.For example,Given 1->2->3->4, you should return the list as 2->1->4->3.Your algorithm should use only constant space.You may not modify the values in the list,only nodes itself can be changed."""classNode(object):def__init__(self,x): self.val = x self.next =Nonedefswap_pairs(head):ifnot head:return head start =Node(0) start.next = head current = startwhile current.next and current.next.next: first = current.next second = current.next.next first.next = second.next current.next = second current.next.next = first current = current.next.nextreturn start.next