def removeNthFromEnd(self, head: 'ListNode', n: 'int') -> 'ListNode':
        refDict = {}
        cnt = 0
        fakeHead = ListNode(None)
        fakeHead.next = head

        while fakeHead is not None:
            cnt += 1
            refDict[cnt] = fakeHead
            fakeHead = fakeHead.next

        # When list is too short, return the original list head directly.
        if cnt > n:
            # The node to be deleted is stored at refDict[cnt - n + 1].
            refDict[cnt - n].next = refDict.get(cnt - n + 2)

        return refDict[1].next
Exemple #2
0
    def partition(self, head: ListNode, x: int) -> ListNode:
        lHead = l = ListNode(0)
        rHead = r = ListNode(0)
        currNode = head
        while currNode:
            if currNode.val < x:
                l.next = currNode
                l = l.next
            else:
                r.next = currNode
                r = r.next

            currNode = currNode.next

        # Note that the current r should be the last node in the new list.
        r.next = None
        l.next = rHead.next
        return lHead.next
Exemple #3
0
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        Cheat answer: python does not have a limit on integer.
        """
        def get_number(l: ListNode) -> int:
            rslt, curr = 0, l
            while curr:
                rslt = rslt * 10 + curr.val
                curr = curr.next

            return rslt

        n = str(get_number(l1) + get_number(l2))
        dummyHead = currNode = ListNode(None)
        for c in n:
            currNode.next = ListNode(int(c))
            currNode = currNode.next

        return dummyHead.next
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        newHead = preHead = ListNode(None)
        newHead.next = currHead = head
        while currHead:
            if currHead.val == val:
                preHead.next = currHead.next
            else:
                preHead = preHead.next

            currHead = currHead.next

        return newHead.next
Exemple #5
0
    def swapPairs(self, head: 'ListNode') -> 'ListNode':
        fakeHead = ListNode(None)
        pre = fakeHead
        pre.next = head

        while pre.next and pre.next.next:
            n1 = pre.next
            n2 = n1.next
            pre.next, n1.next, n2.next = n2, n2.next, n1
            pre = n1

        return fakeHead.next
Exemple #6
0
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        fakeHead = ListNode(None)
        fakeHead.next = l = r = head
        jump, cnt = fakeHead, 0

        while True:
            cnt = 0

            while r and cnt < k:  # Advance r until it points to Node(k+1).
                cnt += 1
                r = r.next

            if cnt == k:  # List is long enough to hold a k group.
                pre, curr = r, l

                for _ in range(k):  # Swap k times to reverse the k group.
                    """   
                    It reverses each node by cutting it from the k group,
                    then pre-append it with the rest of the list 
                    after the k group.

                    Each loop cuts one node starting from the last node in the
                    k group to the first node.

                    For example:
                        Initiallly:
                            k = 3
                            pre = 4 -> None
                            curr = 1 -> 2 -> 3 -> 4 -> None
                        Round 0:
                            pre = 1 -> 4 -> None
                            curr = 2 -> 3 -> 4 -> None
                        Round 1:
                            pre = 2 -> 1 -> 4 -> None
                            curr = 3 -> 4 -> None
                        Round 2:
                            pre = 3 -> 2 -> 1 -> 4 -> None
                            curr = 4 -> None
                        Now the nodes in the k group is reversed and stored in
                        pre.
                    """
                    temp = curr.next  # Store curr.next for later reference.
                    curr.next = pre  # Pre-append current node to the remain.
                    pre = curr  # Move remain pointer to the current node.
                    curr = temp  # Move current node to the previous next node.

                jump.next = pre  # Append the reversed node list to fakeHead.
                jump = l  # Move jump to the end point of the current k group.
                l = r  # Set l to the first item in the next k group.
            else:  # List is exhausted.
                return fakeHead.next
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        rslt = preNode = ListNode(0)
        preNode.next = currNode = head
        while currNode and currNode.next:
            if currNode.val == currNode.next.val:
                currNode = currNode.next
                while currNode and currNode.next and \
                        currNode.val == currNode.next.val:
                    currNode = currNode.next

                preNode.next = currNode = currNode.next
            else:
                preNode = preNode.next
                currNode = currNode.next

        return rslt.next
Exemple #8
0
    def mergeTwoLists(self, l1: 'ListNode', l2: 'ListNode') -> 'ListNode':
        dumyHead = ListNode(None)
        temp = dumyHead

        while l1 and l2:
            if l1.val > l2.val:
                temp.next = l2
                l2 = l2.next
            else:
                temp.next = l1
                l1 = l1.next
            temp = temp.next

        if l1:
            temp.next = l1

        if l2:
            temp.next = l2

        return dumyHead.next
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        # Presumption: 1 <= m <= n <= length of the list.
        rslt = preNode = ListNode(0)
        preNode.next = currNode = head
        cnt = 1
        while cnt < m:  # Move to the Node m.
            preNode, currNode = preNode.next, currNode.next
            cnt += 1

        tailNode, nextNode = currNode, currNode.next
        tailNode.next = None
        while cnt < n:  # Move to the Node n.
            tempNode = nextNode.next
            nextNode.next = currNode
            currNode = nextNode
            nextNode = tempNode
            cnt += 1

        tailNode.next = nextNode
        preNode.next = currNode
        return rslt.next
"""
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
"""

from test_helper import ListNode


class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        rslt = preNode = ListNode(0)
        preNode.next = currNode = head
        while currNode and currNode.next:
            if currNode.val == currNode.next.val:
                currNode = currNode.next
                while currNode and currNode.next and \
                        currNode.val == currNode.next.val:
                    currNode = currNode.next

                preNode.next = currNode = currNode.next
            else:
                preNode = preNode.next
                currNode = currNode.next

        return rslt.next


a = ListNode(0).create_node_list(givenList=[1, 1])
print(Solution().deleteDuplicates(a))
    def removeNthFromEnd(self, head: 'ListNode', n: 'int') -> 'ListNode':
        refDict = {}
        cnt = 0
        fakeHead = ListNode(None)
        fakeHead.next = head

        while fakeHead is not None:
            cnt += 1
            refDict[cnt] = fakeHead
            fakeHead = fakeHead.next

        # When list is too short, return the original list head directly.
        if cnt > n:
            # The node to be deleted is stored at refDict[cnt - n + 1].
            refDict[cnt - n].next = refDict.get(cnt - n + 2)

        return refDict[1].next


x = ListNode(None).create_node_list(1, 2)
print('Original List:')
x.print_node_list()
offset = 1
print('Removing {0}th node from the end of the list...'.format(offset))
print('Updated List:')
y = Solution().removeNthFromEnd(x, offset)
if y is not None:
    y.print_node_list()
else:
    print(y)
Exemple #12
0
"""
https://leetcode.com/problems/swapping-nodes-in-a-linked-list/
"""


from test_helper import ListNode


class Solution:
    def swapNodes(self, head: ListNode, k: int) -> ListNode:
        currNode, rKthNode = head, None
        cnt = 0
        kthNode = None
        while currNode:
            if rKthNode:
                rKthNode = rKthNode.next

            cnt += 1
            if cnt == k:
                rKthNode = head
                kthNode = currNode

            currNode = currNode.next

        kthNode.val, rKthNode.val = rKthNode.val, kthNode.val
        return head


head = ListNode(1)
print(Solution().swapNodes(head, 1))
Exemple #13
0
"""
https://leetcode.com/problems/remove-duplicates-from-sorted-list/
"""

from test_helper import ListNode


class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        currNode = head
        while currNode and currNode.next:
            if currNode.val == currNode.next.val:
                currNode.next = currNode.next.next
            else:
                currNode = currNode.next

        return head


head = ListNode(0).create_node_list(givenList=[1, 1, 2])
print(Solution().deleteDuplicates(head))
Exemple #14
0
        # Find the middle node of the list first.
        middleNode, tailNode = head, head.next
        while tailNode and tailNode.next:
            middleNode = middleNode.next
            tailNode = tailNode.next.next

        currNode, nextNode = middleNode.next, middleNode.next.next

        # Cut the list at the middle point.
        middleNode.next, currNode.next = None, None

        # Reverse the half list starting at the currNode.
        while nextNode:
            tempNode = nextNode.next
            nextNode.next = currNode
            currNode = nextNode
            nextNode = tempNode

        # Merge the two lists.
        currNode, nextNode = head, currNode
        while currNode:
            tempNode = currNode.next
            currNode.next = nextNode
            currNode = nextNode
            nextNode = tempNode


root = ListNode(None).create_node_list(1, 5)
Solution().reorderList(root)
print(root.print_single_list())
Exemple #15
0
from test_helper import ListNode


class Solution:
    def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]:
        if not root:
            return [None] * k

        # First calculate the total length of the list.
        currNode, total = root, 0
        while currNode:
            total += 1
            currNode = currNode.next

        partLen, remainLen = divmod(total, k)
        currNode, rslt, partCnt = root, [], 0
        for partCnt in range(k):  # Split list to parts with partLen length.
            rslt.append(currNode)
            for _ in range(partLen + (partCnt < remainLen)):
                preNode, currNode = currNode, currNode.next

            preNode.next = None

        return rslt


root = ListNode(1)
root.create_node_list(1, 11)
print(Solution().splitListToParts(root.next, 3))
"""
https://leetcode.com/problems/linked-list-components/
"""

from test_helper import ListNode


class Solution:
    def numComponents(self, head: ListNode, G: list[int]) -> int:
        cnt = 0
        nodes = set(G)
        currNode = head
        while currNode and nodes:
            nextNode = currNode.next
            if nextNode:
                if currNode.val in nodes and nextNode.val not in nodes:
                    cnt += 1
            elif currNode.val in nodes:
                cnt += 1

            currNode = nextNode

        return cnt


head = ListNode(None).create_node_list(0, 4)
print(Solution().numComponents(head, [0, 1, 3]))
 def deleteNode(self, node: ListNode):
     node.val = node.next.val
     node.next = node.next.next
Exemple #18
0
        """
        Use bottom-up merge sort to achieve 
        the o(nlogn) runtime and the o(1) space.
        """
        if not head or not head.next:  # Empty or only one node.
            return head

        # Get the total size of the list first.
        n, currNode = 0, head
        while currNode:
            n, currNode = n + 1, currNode.next

        # Keep cutting and merging the sub lists.
        step, dummyHead = 1, ListNode(None)
        dummyHead.next = head
        while step < n:
            currHead, currTail = dummyHead.next, dummyHead
            while currHead:
                leftHead = currHead
                rightHead = self._cut_list(leftHead, step)
                currHead = self._cut_list(rightHead, step)
                currTail = self._merge_list(leftHead, rightHead, currTail)

            step *= 2

        return dummyHead.next


head = ListNode(None).create_node_list(givenList=[6, 5, 4, 3, 2, 1])
print(Solution().sortList(head).print_single_list())
        4.  So now the slow has to be moved s1 steps in order to get to the
            start point of the cycle, while the fast is now at k + 1 + s1 - r
            = r + s1 - r = s1, which is also the start point of the cycle. So
            now we have finally found the start point of the cycle.
        """
        if not head or not head.next:
            return None

        # Try to find the meet point when the fast just runs one more cycle.
        # than the slow.
        slow, fast = head, head.next
        while slow != fast:
            if not fast or not fast.next:  # The fast reaches the end.
                return None

            slow = slow.next
            fast = fast.next.next

        slow, fast = head, fast.next
        while slow != fast:
            slow = slow.next
            fast = fast.next

        # Now both the slow and fast points to the cycle start point.
        return slow


print(Solution().detectCycle(
    ListNode(None).create_cycle_list([3, 2, 0, -4], 1)))
from test_helper import ListNode


class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        # Presumption: 1 <= m <= n <= length of the list.
        rslt = preNode = ListNode(0)
        preNode.next = currNode = head
        cnt = 1
        while cnt < m:  # Move to the Node m.
            preNode, currNode = preNode.next, currNode.next
            cnt += 1

        tailNode, nextNode = currNode, currNode.next
        tailNode.next = None
        while cnt < n:  # Move to the Node n.
            tempNode = nextNode.next
            nextNode.next = currNode
            currNode = nextNode
            nextNode = tempNode
            cnt += 1

        tailNode.next = nextNode
        preNode.next = currNode
        return rslt.next


print(Solution().reverseBetween(ListNode(0).create_node_list(
    givenList=[1]), 1, 1))
Exemple #21
0
"""
https://leetcode.com/problems/swap-nodes-in-pairs/
"""

from test_helper import ListNode


class Solution:
    def swapPairs(self, head: 'ListNode') -> 'ListNode':
        fakeHead = ListNode(None)
        pre = fakeHead
        pre.next = head

        while pre.next and pre.next.next:
            n1 = pre.next
            n2 = n1.next
            pre.next, n1.next, n2.next = n2, n2.next, n1
            pre = n1

        return fakeHead.next


l = ListNode(None).create_node_list(givenList=[1, 2, 3, 4])
print('The original list is:')
print(l)
print('The swapped list is:')
print(Solution().swapPairs(l))
Exemple #22
0
class Solution:
    def insertionSortList(self, head: ListNode) -> ListNode:
        dummyHead = ListNode(None)
        currNode, dummyHead.next, preInsertPos = head, head, dummyHead
        while currNode and currNode.next:
            # The current node always points to the end of the sorted sequece.
            nextVal = currNode.next.val
            if nextVal < currNode.val:
                # The next node needs to be inserted to the current sequence.
                # Try to find the insert position first.
                if nextVal < preInsertPos.next.val:
                    preInsertPos = dummyHead

                while preInsertPos.next and preInsertPos.next.val <= nextVal:
                    preInsertPos = preInsertPos.next

                # Insert the nextNode between preInsertPos
                # and preInsertPos.next.
                newNode = currNode.next
                currNode.next = newNode.next
                newNode.next = preInsertPos.next
                preInsertPos.next = newNode
            else:
                currNode = currNode.next  # Sort the next node.

        return dummyHead.next


head = ListNode(None).create_node_list(givenList=[4, 2, 1, 3])
print(Solution().insertionSortList(head).print_single_list())
Exemple #23
0
                        Initiallly:
                            k = 3
                            pre = 4 -> None
                            curr = 1 -> 2 -> 3 -> 4 -> None
                        Round 0:
                            pre = 1 -> 4 -> None
                            curr = 2 -> 3 -> 4 -> None
                        Round 1:
                            pre = 2 -> 1 -> 4 -> None
                            curr = 3 -> 4 -> None
                        Round 2:
                            pre = 3 -> 2 -> 1 -> 4 -> None
                            curr = 4 -> None
                        Now the nodes in the k group is reversed and stored in
                        pre.
                    """
                    temp = curr.next  # Store curr.next for later reference.
                    curr.next = pre  # Pre-append current node to the remain.
                    pre = curr  # Move remain pointer to the current node.
                    curr = temp  # Move current node to the previous next node.

                jump.next = pre  # Append the reversed node list to fakeHead.
                jump = l  # Move jump to the end point of the current k group.
                l = r  # Set l to the first item in the next k group.
            else:  # List is exhausted.
                return fakeHead.next


x = ListNode(None)
print(Solution().reverseKGroup(x.create_node_list(1, 5), 3))
                        tempNode.next = l1
                        l1 = l1.next
                    else:
                        tempNode.next = l2
                        l2 = l2.next
                    tempNode = tempNode.next

                if l1:
                    tempNode.next = l1

                if l2:
                    tempNode.next = l2

                lists[i] = fakeHead.next  # Store merged list back to lists[i].

            interval *= 2  # Increase interval.

        return lists[0]


x = ListNode(None)
s = Solution()
l1 = x.create_node_list(givenList=[1, 4, 5])
l2 = x.create_node_list(givenList=[1, 3, 4])
l3 = x.create_node_list(givenList=[2, 6])
print('Original list is: ')
for l in [l1, l2, l3]:
    l.print_node_list()
print('Merged list is:')
s.mergeKLists([l1, l2, l3]).print_node_list()
Exemple #25
0
"""
https://leetcode.com/problems/partition-list/
"""

from test_helper import ListNode


class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        lHead = l = ListNode(0)
        rHead = r = ListNode(0)
        currNode = head
        while currNode:
            if currNode.val < x:
                l.next = currNode
                l = l.next
            else:
                r.next = currNode
                r = r.next

            currNode = currNode.next

        # Note that the current r should be the last node in the new list.
        r.next = None
        l.next = rHead.next
        return lHead.next


head = ListNode(0).create_node_list(givenList=[1, 4, 3, 2, 5, 2])
print(Solution().partition(head, 3))