You are given the head
of a singly linked list, and an integer k
. Your task is to return the head
of the linked list after swapping the values of the k
th node from the beginning and the k
th node from the end. Note that the list is 1-indexed.
Example 1:
Input: head = [1,2,3,4,5], k = 2
Output: [1,4,3,2,5]
In this example, the 2nd node from the beginning is 2, and the 2nd node from the end is 4. After swapping their values, the list becomes [1,4,3,2,5]
.
Example 2:
Input: head = [7,9,6,6,7,8,3,0,9,5], k = 5
Output: [7,9,6,6,8,7,3,0,9,5]
Here, the 5th node from the beginning is 7, and the 5th node from the end is 8. Swapping them results in [7,9,6,6,8,7,3,0,9,5]
.
Constraints:
n
.1 <= k <= n <= 10^5
0 <= Node.val <= 100
Consider the following when writing your solution:
Can you implement an efficient algorithm to solve this problem?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method for swapping nodes in a linked list involves checking every single possible pair of nodes to swap and evaluating the resulting list. It's like trying every combination until you find the right one. This ensures we explore every possibility, but it might take a while.
Here's how the algorithm would work step-by-step:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def brute_force_swap_nodes(head):
current_node = head
while current_node:
next_node = current_node.next
while next_node:
# Attempt to swap the values of the current node with the next node
current_node.val, next_node.val = next_node.val, current_node.val
# Move to the next node for further potential swaps
next_node = next_node.next
current_node = current_node.next
return head
To swap two nodes in a linked list efficiently, focus on adjusting the connections of the nodes around the ones you want to swap. This avoids unnecessary changes to the rest of the list and lets you swap the nodes by modifying only a few connections.
Here's how the algorithm would work step-by-step:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def swap_nodes(head, first_node_value, second_node_value):
if first_node_value == second_node_value:
return head
previous_node_first_node = None
current_node_first_node = head
while current_node_first_node and current_node_first_node.val != first_node_value:
previous_node_first_node = current_node_first_node
current_node_first_node = current_node_first_node.next
previous_node_second_node = None
current_node_second_node = head
while current_node_second_node and current_node_second_node.val != second_node_value:
previous_node_second_node = current_node_second_node
current_node_second_node = current_node_second_node.next
# If either node is not found, return the original list.
if not current_node_first_node or not current_node_second_node:
return head
# Update the 'previous' pointer of the first node.
if previous_node_first_node:
previous_node_first_node.next = current_node_second_node
else:
# If the first node is the head, update the head.
head = current_node_second_node
# Update the 'previous' pointer of the second node.
if previous_node_second_node:
previous_node_second_node.next = current_node_first_node
else:
# If the second node is the head, update the head.
head = current_node_first_node
# Swap the next pointers of the two nodes.
temporary_node = current_node_first_node.next
current_node_first_node.next = current_node_second_node.next
current_node_second_node.next = temporary_node
return head
Case | How to Handle |
---|---|
Empty list (head is null) | Return null immediately as there are no nodes to swap. |
List with only one node | Return the head as is since no swapping is needed. |
List with two nodes and k=1 | Swap the first and last (which are the only two) nodes and return the head. |
k is greater than the list length | Do nothing, or return an error; the swap should not modify the list and the original list should be returned. |
k is equal to the list length | Swap the first and last nodes and return the head. |
k is 1 | Swap the first and last node in the list. |
k is in the middle of the list, but the kth node from the beginning and the kth node from the end are the same node | No swap is needed; return the head as is. |
Large list to verify performance and potential memory issues if using auxiliary data structures | The iterative solution should scale efficiently without causing memory issues. |