# @return the intersected ListNode def getIntersectionNode(self, headA, headB): if not headA or not headB: return None pA,pB,tailA,tailB = headA,headB,None,None while True: if not pA: pA = headB if not pB: pB = headA if not pA.next: tailA = pA if not pB.next: tailB = pB #The two links have different tails. So just return null; if tailA and tailB and tailA!=tailB: return None if pA == pB: return pA pA, pB = pA.next, pB.next if __name__=="__main__": l1 = LListUtil.buildList([2,3]) l2 = LListUtil.buildList([4,5,6]) l3 = LListUtil.buildList([8,9,10]) l1.next.next = l3; l2.next.next.next = l3 LListUtil.printList(l1); LListUtil.printList(l2); print (Solution().getIntersectionNode(l1,l2)).val """ Two pointer solution (O(n+m) running time, O(1) memory): (Standard solution) Maintain two pointers pA and pB initialized at the head of A and B, respectively. Then let them both traverse through the lists, one node at a time. When pA reaches the end of a list, then redirect it to the head of B (yes, B, that's right.); similarly when pB reaches the end of a list, redirect it the head of A. If at any point pA meets pB, then pA/pB is the intersection node. """
curr, listLen = head, 0 while curr: curr, listLen = curr.next, listLen + 1 curr, prev, index = head, dumhead, 1 prehead, preheadnext = dumhead, head while curr: if listLen - index < listLen % k: break nextN = curr.next curr.next = prev if index % k == 0: prehead.next = curr preheadnext.next = nextN prehead = preheadnext prev = prehead preheadnext = nextN else: prev = curr curr, index = nextN, index + 1 return dumhead.next if __name__ == "__main__": arr = range(1, 10) head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().reverseKGroup(head, 4)) """ Simliar as problem 'Swap Nodes in Pairs'. when index meet times of K (index%K==0), then reverse the list segement. Notice, for the last few nodes (list_Length-index < list_Length%k) do nothing. """
path1.append(path2.dirname(path2.dirname(path2.abspath(__file__)))) import LListUtil # Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNode # @return a ListNode def deleteDuplicates(self, head): if not head or not head.next: return head curr = head while curr.next: if curr.next.val == curr.val: curr.next = curr.next.next else: curr = curr.next return head if __name__ == "__main__": arr = [1, 1, 2, 3, 3] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().deleteDuplicates(head))
if not head: return head pivot = ListNode(0) pivot.next = head prev = None while pivot and pivot.val < x: prev = pivot pivot = pivot.next if pivot: curr = prev while pivot: if pivot.val < x: temp = curr.next prev.next = pivot.next curr.next = pivot curr = pivot pivot.next = temp pivot = prev prev = pivot pivot = pivot.next return head if __name__=="__main__": arr = [1,4,3,2,5,2] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().partition(head,3)) """ Scan from left to right, if met a node(pivot node) value larger than X, then insert all small nodes found later into the left of pivot node. """
# Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @return a ListNode def removeNthFromEnd(self, head, n): if not head: return head dumhead = ListNode(0) dumhead.next = head head = prev = dumhead count = 0 while head.next: head = head.next count += 1 if count > n: prev = prev.next prev.next = prev.next.next return dumhead.next if __name__ == "__main__": arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().removeNthFromEnd(head, 9))
# @return a ListNode def mergeTwoLists(self, l1, l2): dumhead = ListNode(0) curr = dumhead while True: if not l1: curr.next = l2 break if not l2: curr.next = l1 break if l1.val < l2.val: curr.next = l1 l1 = l1.next else: curr.next = l2 l2 = l2.next curr = curr.next return dumhead.next if __name__=="__main__": arr1 = LListUtil.randomArr(10,5) arr2 = LListUtil.randomArr(10,5) arr1.sort(); arr2.sort() l1 = LListUtil.buildList(arr1) l2 = LListUtil.buildList(arr2) LListUtil.printList(l1) LListUtil.printList(l2) sol = Solution() LListUtil.printList(sol.mergeTwoLists(l1,l2))
class Solution: # @return a ListNode def addTwoNumbers(self, l1, l2): dumhead = ListNode(0) carry = 0 head = dumhead while carry or l1 or l2: node = ListNode(carry) if l1: node.val += l1.val l1 = l1.next if l2: node.val += l2.val l2 = l2.next carry = node.val / 10 node.val %= 10 head.next = node head = head.next return dumhead.next if __name__ == "__main__": arr1 = LListUtil.randomArr(10, 5) arr2 = LListUtil.randomArr(10, 5) l1 = LListUtil.buildList(arr1) l2 = LListUtil.buildList(arr2) LListUtil.printList(l1) LListUtil.printList(l2) LListUtil.printList(Solution().addTwoNumbers(l1, l2))
if not head: return head pivot = ListNode(0) pivot.next = head prev = None while pivot and pivot.val < x: prev = pivot pivot = pivot.next if pivot: curr = prev while pivot: if pivot.val < x: temp = curr.next prev.next = pivot.next curr.next = pivot curr = pivot pivot.next = temp pivot = prev prev = pivot pivot = pivot.next return head if __name__ == "__main__": arr = [1, 4, 3, 2, 5, 2] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().partition(head, 3)) """ Scan from left to right, if met a node(pivot node) value larger than X, then insert all small nodes found later into the left of pivot node. """
import LListUtil # Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNode # @return a ListNode def deleteDuplicatesII(self, head): if not head or not head.next: return head dumhead = ListNode(0) dumhead.next = head prev = dumhead while prev.next: curr = prev.next while curr.next and curr.val==curr.next.val: curr = curr.next if curr != prev.next: prev.next = curr.next else: prev = prev.next return dumhead.next if __name__=="__main__": arr = [1,2,3,3,4,4,5] # [1,1,1,2,3] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().deleteDuplicatesII(head))
dumhead.next = head curr, listLen = head, 0 while curr: curr, listLen = curr.next, listLen+1 curr, prev, index = head, dumhead, 1 prehead, preheadnext = dumhead, head while curr: if listLen-index < listLen%k: break nextN = curr.next curr.next = prev if index%k == 0: prehead.next = curr preheadnext.next = nextN prehead = preheadnext prev = prehead preheadnext = nextN else: prev = curr curr, index = nextN, index+1 return dumhead.next if __name__=="__main__": arr = range(1,10) head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().reverseKGroup(head,4)) """ Simliar as problem 'Swap Nodes in Pairs'. when index meet times of K (index%K==0), then reverse the list segement. Notice, for the last few nodes (list_Length-index < list_Length%k) do nothing. """
# now slow is the mid point and do reverse fast = slow.next while fast.next: temp = slow.next slow.next = fast.next fast.next = fast.next.next slow.next.next = temp # insert reverse part fast = head while slow != fast and slow.next: temp = fast.next fast.next = slow.next slow.next = slow.next.next fast.next.next = temp fast = fast.next.next if __name__ == "__main__": arr = list(range(1, 10)) head = LListUtil.buildList(arr) LListUtil.printList(head) Solution().reorderList(head) LListUtil.printList(head) ''' So the algorithm implemented below can be summarized as: Step 1 Find the middle pointer of the linked list (you can use the slow/fast pointers) Step 2 Reverse the second part of the linked list (from middle->next to the end) Step 3 Do the reordering. (inset every element in the second part in between the elements in the first part) '''
alen,blen = getsize(headA),getsize(headB) if alen > blen: while alen > blen: headA = headA.next; alen -= 1 else: while blen > alen: headB = headB.next; blen -= 1 while headA: if headA == headB: return headA headA, headB = headA.next, headB.next return None if __name__=="__main__": l1 = LListUtil.buildList([2,3]) l2 = LListUtil.buildList([4,5,6]) l3 = LListUtil.buildList([8,9,10]) l1.next.next = l3; l2.next.next.next = l3 LListUtil.printList(l1); LListUtil.printList(l2); print (Solution().getIntersectionNode(l1,l2)).val """ Get both list length, then start to traverse from the shorter length. e.g. a1 -> a2 | \ | c1 -> c2 -> c3 | / b1 ->|b2 -> b3 v
# @return a ListNode def reverseBetween(self, head, m, n): for i in range(n-m): index1 = n - i index2 = m + i if index2 >= index1: return head first, second = head, head while index1-1>0: first,index1 = first.next,index1-1 while index2-1>0: second,index2 = second.next,index2-1 first.val, second.val = second.val, first.val return head if __name__=="__main__": arr = list(range(1,10)) sol = Solution() head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(sol.reverseBetween(head,1,8)) """ This is easy way which reverses just value of nodes. (1) the stop condition is the middle of the reversed sublist (m+n)/2 (2) for each element in the sublist, the swapping element is the next (n-m-(i-m)*2) element. e.g. 1-2-3-4-5-6-7-8-9-10-null | | m=2 n=9 for 2, just get the next (n-m) element. 1-9-3-4-5-6-7-8-2-10-null
second = dumhead count = 0 while count < n - 1 and first.next: first = first.next count += 1 if count > n - m: second = second.next if not first.next: return None temp1 = first.next.next curr = second.next prev = None while curr != temp1: temp2 = curr.next curr.next = prev prev = curr curr = temp2 second.next = prev if curr: while prev.next: prev = prev.next prev.next = curr return dumhead.next if __name__ == "__main__": arr = list(range(1, 10)) sol = Solution() head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(sol.reverseBetween(head, 1, 8))
""" from sys import path as path1; from os import path as path2 path1.append(path2.dirname(path2.dirname(path2.abspath(__file__)))) import LListUtil # Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNode # @return a boolean def hasCycle(self, head): if not head: return False fast = head slow = head while fast and fast.next: fast = fast.next.next slow = slow.next if slow == fast: return True return False if __name__=="__main__": import random arr = list(range(10)) sol = Solution() head = LListUtil.buildList(arr) print sol.hasCycle(head)
head = head.next print def buildList(arr): head = ListNode(0) curr = head for i in arr: curr.next = ListNode(i) curr = curr.next return head.next if __name__ == "__main__": arr = list(range(1, 10)) head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().swapTwoLinkedList(head, 8, 9)) LListUtil.printList(Solution().swapTwoLinkedList2(head, 1, 9)) ''' swap two nodes in linked list scheme:: nide1->node2->node3->nide4 first swap node1.next with node2.next node1.next = node2.next node2.next = node2 second swap node2.next with node3.next node2.next = node4 node3.next = node2 '''
class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNod # @return a ListNode def reverseLinkedList(self, head): if not head: return None dumhead = ListNode(0) dumhead.next = head prev = dumhead curr = prev.next while curr.next: temp = prev.next prev.next = curr.next curr.next = curr.next.next prev.next.next = temp return dumhead.next if __name__=="__main__": arr = list(range(1,10)) sol = Solution() head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(sol.reverseLinkedList(head)) """ Alternative way, fixed prev and curr val, and move curr to the end """
def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNode # @param k, an integer # @return a ListNode def rotateRight(self, head, k): if not head or k==0: return head curr, listLen = head, 1 while curr.next: curr, listLen = curr.next, listLen+1 k = listLen - k % listLen if k == listLen: return head curr.next, index = head, 0 while index < k: curr, index = curr.next, index+1 head = curr.next curr.next = None return head if __name__=="__main__": arr = list(xrange(1,6)) head = LListUtil.buildList(arr) k = 2 LListUtil.printList(head) LListUtil.printList(Solution().rotateRight(head,k)) """ First, get the length of the list, then make last node.next point to head. Second, iterate from head until length-k%length, then break the node. """
self.next = None class Solution: # @return a ListNode def addTwoNumbers(self, l1, l2): dumhead = ListNode(0) carry = 0 head = dumhead while carry or l1 or l2: node = ListNode(carry) if l1: node.val += l1.val l1 = l1.next if l2: node.val += l2.val l2 = l2.next carry = node.val / 10 node.val %= 10 head.next = node head = head.next return dumhead.next if __name__=="__main__": arr1 = LListUtil.randomArr(10,5) arr2 = LListUtil.randomArr(10,5) l1 = LListUtil.buildList(arr1) l2 = LListUtil.buildList(arr2) LListUtil.printList(l1) LListUtil.printList(l2) LListUtil.printList(Solution().addTwoNumbers(l1,l2))
# Time Limit Exceeded def mergeKLists(self, lists): if len(lists) == 0: return None head = ListNode(0) head.next = lists[0] for l2 in lists[1:]: l1 = head while l2: if not l1.next: l1.next = l2 break if l1.next.val < l2.val: l1 = l1.next else: temp = l1.next l1.next = l2 l2 = l2.next l1.next.next = temp l1 = l1.next return head.next if __name__=="__main__": l1 = sorted(LListUtil.randomArr(100,5)) l2 = sorted(LListUtil.randomArr(100,5)) l3 = sorted(LListUtil.randomArr(100,5)) l4 = sorted(LListUtil.randomArr(100,5)) l5 = sorted(LListUtil.randomArr(100,5)) lists = [LListUtil.buildList(l1),LListUtil.buildList(l2),LListUtil.buildList(l3),LListUtil.buildList(l4),LListUtil.buildList(l5)] LListUtil.printLists(lists) LListUtil.printList(Solution().mergeKLists(lists))
curr = ListNode(0) curr.next = head head = curr while True: if not curr.next: break if not curr.next.next: break p1 = curr.next p2 = p1.next p1.next = p2.next p2.next = p1 curr.next = p2 curr = p1 return head.next if __name__ == "__main__": arr = list(range(1, 10)) head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().swapPairs(head)) ''' swap two nodes in linked list scheme:: nide1->node2->node3->nide4 first swap node1.next with node2.next node1.next = node2.next node2.next = node2 second swap node2.next with node3.next node2.next = node4 node3.next = node2 '''
curr = ListNode(0) curr.next = head head = curr while True: if not curr.next: break if not curr.next.next: break p1 = curr.next p2 = p1.next p1.next = p2.next p2.next = p1 curr.next = p2 curr = p1 return head.next if __name__=="__main__": arr = list(range(1,10)) head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().swapPairs(head)) ''' swap two nodes in linked list scheme:: nide1->node2->node3->nide4 first swap node1.next with node2.next node1.next = node2.next node2.next = node2 second swap node2.next with node3.next node2.next = node4 node3.next = node2 '''
# now slow is the mid point and do reverse fast = slow.next while fast.next: temp = slow.next slow.next = fast.next fast.next = fast.next.next slow.next.next = temp # insert reverse part fast = head while slow != fast and slow.next: temp = fast.next fast.next = slow.next slow.next = slow.next.next fast.next.next = temp fast = fast.next.next if __name__=="__main__": arr = list(range(1,10)) head = LListUtil.buildList(arr) LListUtil.printList(head) Solution().reorderList(head) LListUtil.printList(head) ''' So the algorithm implemented below can be summarized as: Step 1 Find the middle pointer of the linked list (you can use the slow/fast pointers) Step 2 Reverse the second part of the linked list (from middle->next to the end) Step 3 Do the reordering. (inset every element in the second part in between the elements in the first part) '''
if slow == fast: flag = True break if not flag: return None fast = head while fast != slow: fast = fast.next slow = slow.next return fast if __name__ == "__main__": import random arr = list(range(10)) sol = Solution() head = LListUtil.buildList(arr) print sol.detectCycle(head) """ Firstly let us assume the slow pointer (S) and fast pointer (F) start at the same place in a n node circle. S run t steps while F can run 2t steps, we want to know what is t (where they meet) , then just solve: t mod n = 2t mod n, we know when t = n, they meet, that is the start of the circle. For our problem, we can consider the time when S enter the loop for the 1st time, which we assume k step from the head. At this time, the F is already in k step ahead in the loop. When will they meet next time? Still solve the function: t mod n = (k + 2t) mod n Finally, when t = (n-k), S and F will meet, this is k steps before the start of the loop.
# Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param head, a ListNod # @return a ListNode def reverseLinkedList(self, head): if not head: return None curr = head prev = None while curr: temp = curr.next curr.next = prev prev = curr curr = temp return prev if __name__ == "__main__": arr = list(range(1, 10)) sol = Solution() head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(sol.reverseLinkedList(head))
# @param head, a ListNode # @return a ListNode def insertionSortList(self, head): if head is None: return None pivot = ListNode(0) pivot.next = head head = pivot while pivot.next: curr = head flag = False while curr != pivot: if curr.next.val > pivot.next.val: temp = pivot.next pivot.next = pivot.next.next temp.next = curr.next curr.next = temp flag = True break else: curr = curr.next if not flag: pivot = pivot.next return head.next if __name__=="__main__": arr = LListUtil.randomArr(20,10) sol = Solution() head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(sol.insertionSortList(head))
path1.append(path2.dirname(path2.dirname(path2.abspath(__file__)))) import LListUtil # Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @return a ListNode def removeNthFromEnd(self, head, n): if not head: return head dumhead = ListNode(0) dumhead.next = head head = prev = dumhead count = 0 while head.next: head = head.next count += 1 if count > n: prev = prev.next prev.next = prev.next.next return dumhead.next if __name__=="__main__": arr = [1,2,3,4,5,6,7,8,9] head = LListUtil.buildList(arr) LListUtil.printList(head) LListUtil.printList(Solution().removeNthFromEnd(head,9))