Taro Logo

Maximum Twin Sum of a Linked List

Medium
Apple logo
Apple
1 view
Topics:
Linked ListsStacksTwo Pointers

In a linked list of size n, where n is even, the ith node (0-indexed) of the linked list is known as the twin of the (n-1-i)th node, if 0 <= i <= (n / 2) - 1.

  • For example, if n = 4, then node 0 is the twin of node 3, and node 1 is the twin of node 2. These are the only nodes with twins for n = 4.

The twin sum is defined as the sum of a node and its twin.

Given the head of a linked list with even length, return the maximum twin sum of the linked list.

Example 1:

Input: head = [5,4,2,1] Output: 6 Explanation: Nodes 0 and 1 are the twins of nodes 3 and 2, respectively. All have twin sum = 6. There are no other nodes with twins in the linked list. Thus, the maximum twin sum of the linked list is 6.

Example 2:

Input: head = [4,2,2,3] Output: 7 Explanation: The nodes with twins present in this linked list are: - Node 0 is the twin of node 3 having a twin sum of 4 + 3 = 7. - Node 1 is the twin of node 2 having a twin sum of 2 + 2 = 4. Thus, the maximum twin sum of the linked list is max(7, 4) = 7.

Example 3:

Input: head = [1,100000] Output: 100001 Explanation: There is only one node with a twin in the linked list having twin sum of 1 + 100000 = 100001.

Constraints:

  • The number of nodes in the list is an even integer in the range [2, 10^5]. (Important Edge Case!)
  • 1 <= Node.val <= 10^5

Can you write a function to solve this problem in an efficient manner? What is the time and space complexity of your solution?

Solution


Naive Approach: Brute Force

One straightforward approach is to iterate through the linked list, store the values in an array, and then calculate the twin sums by comparing elements from the start and end of the array. Finally, find the maximum twin sum.

Algorithm:

  1. Traverse the linked list and store the value of each node in an array.
  2. Initialize max_twin_sum to 0.
  3. Iterate from i = 0 to n / 2 - 1:
    • Calculate twin_sum = array[i] + array[n - 1 - i].
    • Update max_twin_sum = max(max_twin_sum, twin_sum).
  4. Return max_twin_sum.

Code (Python):

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def pairSum_brute_force(head: ListNode) -> int:
    arr = []
    curr = head
    while curr:
        arr.append(curr.val)
        curr = curr.next
    
    n = len(arr)
    max_sum = 0
    for i in range(n // 2):
        max_sum = max(max_sum, arr[i] + arr[n - 1 - i])
    
    return max_sum

Time Complexity: O(n) for traversing the linked list and O(n/2) which simplifies to O(n) for calculating twin sums, resulting in O(n) overall.

Space Complexity: O(n) for storing the linked list values in an array.

Optimal Approach: Using a Stack and Two Pointers

A more efficient approach involves using a stack to store the values of the first half of the linked list. Then, we can iterate through the second half of the list and calculate the twin sums by pairing each node with the value popped from the stack. This avoids the need for an additional array.

Algorithm:

  1. Use slow and fast pointers to find the middle of the linked list. The slow pointer will point to the middle.
  2. Push the first half of the linked list into a stack as you traverse it using the slow pointer.
  3. Move slow pointer to the second half and pop from stack to find twin.
  4. Return the maximum of the twin sums.

Code (Python):

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def pairSum(head: ListNode) -> int:
    slow, fast = head, head
    stack = []
    
    # Traverse the first half of linked list and push into stack
    while fast and fast.next:
        stack.append(slow.val)
        slow = slow.next
        fast = fast.next.next
    
    max_sum = 0
    # Traverse the second half and compare with stack
    while slow:
        max_sum = max(max_sum, slow.val + stack.pop())
        slow = slow.next
        
    return max_sum

Time Complexity: O(n) for traversing the linked list.

Space Complexity: O(n/2) which simplifies to O(n) for the stack, as it stores roughly half the elements of the linked list.

Edge Cases:

  • Empty List: The problem statement specifies that the list will have at least 2 nodes, so an empty list isn't an edge case to worry about.
  • List with only two nodes: Both algorithms will function correctly.

Summary:

The optimal solution provides the same O(n) time complexity, but reduces the space complexity from O(n) (for the brute force method) to O(n/2) by utilizing stack which is still O(n). This makes it more space-efficient, particularly for large linked lists.