}
// Find the kth node from beginning of linked list. We also find
// previous of kth node because we need to update next pointer of
// the previous.
ListNode x = head;
ListNode x_prev = null;
for (int i = 1; i < k; i++)
{
x_prev = x;
x = x.next;
}
// Similarly, find the kth node from end and its previous. kth node
// from end is (n-k+1)th node from beginning
ListNode y = head;
ListNode y_prev = null;
for (int i = 1; i < n-k+1; i++)
{
y_prev = y;
y = y.next;
}
// If x_prev exists, then new next of it will be y. Consider the case
// when y->next is x, in this case, x_prev and y are same. So the statement
// "x_prev->next = y" creates a self loop. This self loop will be broken
// when we change y->next.
//
// x_prev x y_prev y
// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
//
// x_prev y
// 1 -> 2 -> 6 -> 7 -> 8
if (x_prev != null)
x_prev.next = y;
// Same thing applies to y_prev
//
// x y_prev
// 3 -> 4 -> 5
// | |
// ------ < ------
if (y_prev != null)
y_prev.next = x;
// Swap next pointers of x and y. These statements also break self
// loop if x->next is y or y->next is x
//
// x_prev y y_prev x
// 1 -> 2 -> 6 -> 4 -> 5 -> 3 -> 7 -> 8
//
ListNode temp = x.next;
x.next = y.next;
y.next = temp;
// Change head pointers when k is 1 or n
if (k == 1)