02. Swap Kth Nodes from Ends

βœ… GFG solution to swap kth nodes from beginning and end of a singly linked list: efficient pointer manipulation technique with optimal time complexity. πŸš€

The problem can be found at the following link: πŸ”— Question Link

🧩 Problem Description

Given the head of a singly linked list and an integer k, swap the kth node (1-based index) from the beginning and the kth node from the end of the linked list. Return the head of the final formed list and if it's not possible to swap the nodes return the original list.

The task involves identifying two specific nodes based on their positions from opposite ends and performing a complete node swap while maintaining the integrity of the linked list structure.

πŸ“˜ Examples

Example 1

Input: k = 1, List: 1 -> 2 -> 3 -> 4 -> 5
Output: 5 -> 2 -> 3 -> 4 -> 1
Explanation: Here k = 1, hence after swapping the 1st node from the beginning 
and end the new list will be 5 -> 2 -> 3 -> 4 -> 1.

Example 2

Input: k = 2, List: 5 -> 7 -> 8 -> 5 -> 10 -> 3
Output: 5 -> 9 -> 8 -> 5 -> 10 -> 3
Explanation: Here k = 2, hence after swapping the 2nd node from the beginning 
and end the new list will be 5 -> 9 -> 8 -> 5 -> 10 -> 3.

Example 3

πŸ”’ Constraints

  • $1 \le \text{list size} \le 10^4$

  • $1 \le \text{node->data} \le 10^6$

  • $1 \le k \le 10^4$

βœ… My Approach

The optimal approach uses Two-Pointer Technique with careful pointer manipulation to efficiently locate and swap the target nodes:

Optimized Single Pass Algorithm

  1. Length Calculation:

    • Traverse the entire list once to determine the total number of nodes n.

    • Handle edge cases: empty list, k > n, or when kth nodes from both ends are the same.

  2. Node Location:

    • Find the kth node from the beginning (x) along with its previous node (px).

    • Find the kth node from the end (y) along with its previous node (py).

    • The kth node from end is at position (n - k + 1) from the beginning.

  3. Pointer Adjustment:

    • Update previous node pointers to point to the swapped nodes.

    • Handle special cases when either node is the head of the list.

  4. Node Swapping:

    • Swap the next pointers of both target nodes.

    • Update head pointer if necessary (when k = 1 or k = n).

  5. Edge Case Handling:

    • Return original list if k > n or if both nodes are the same (middle node in odd-length list).

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n), where n is the number of nodes in the linked list. We traverse the list a constant number of times (at most 3 passes) to count nodes, locate target nodes, and perform the swap.

  • Expected Auxiliary Space Complexity: O(1), as we only use a constant amount of additional space for pointer variables regardless of the input size.

πŸ§‘β€πŸ’» Code (C++)

⚑ View Alternative Approaches with Code and Analysis

πŸ“Š 2️⃣ Two-Pass Traversal Approach

πŸ’‘ Algorithm Steps:

  1. First pass: Calculate the total length of the linked list

  2. Second pass: Traverse again to locate both target nodes and their predecessors

  3. Perform validation checks for edge cases

  4. Execute the swap operation with proper pointer management

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Two linear passes through the list

  • Auxiliary Space: πŸ’Ύ O(1) - Only pointer variables used

βœ… Why This Approach?

  • Clear separation of length calculation and node finding

  • Easier debugging with distinct phases

  • More readable for educational purposes

πŸ“Š 3️⃣ Recursive Position Finding

πŸ’‘ Algorithm Steps:

  1. Use recursion to traverse to the end while counting positions

  2. During backtracking, identify nodes at target positions

  3. Mark nodes for swapping when positions match k and (n-k+1)

  4. Perform swap operation after recursive traversal completes

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Single recursive traversal

  • Auxiliary Space: πŸ’Ύ O(n) - Recursion stack space

βœ… Why This Approach?

  • Elegant recursive pattern for position tracking

  • Simplifies node identification logic

  • Good for understanding recursive list processing

πŸ“Š 4️⃣ Array-Based Node Storage

πŸ’‘ Algorithm Steps:

  1. Store all node pointers in a vector during single traversal

  2. Use direct indexing to access kth nodes from both ends

  3. Locate predecessor nodes efficiently using array indices

  4. Perform swap with O(1) node access and pointer updates

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Single pass with additional O(1) operations

  • Auxiliary Space: πŸ’Ύ O(n) - Vector storage for all node pointers

βœ… Why This Approach?

  • Direct random access to any node position

  • Simplified predecessor node identification

  • Useful for multiple swap operations on the same list

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Optimized Single Pass

🟒 O(n)

🟒 O(1)

πŸš€ Optimal time & space

πŸ”§ Complex pointer logic

πŸ” Two-Pass Traversal

🟒 O(n)

🟒 O(1)

πŸ“– Clear phase separation

🐌 Multiple list traversals

πŸ“Š Recursive Position Finding

🟒 O(n)

🟑 O(n)

🎯 Elegant recursive pattern

πŸ’Ύ Stack space overhead

πŸ”„ Array-Based Storage

🟒 O(n)

🟑 O(n)

⭐ Random access capability

πŸ’Ύ Extra memory for storage

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Optimal performance needed

πŸ₯‡ Optimized Single Pass

β˜…β˜…β˜…β˜…β˜…

πŸ“– Learning/Educational purposes

πŸ₯ˆ Two-Pass Traversal

β˜…β˜…β˜…β˜…β˜†

πŸ”§ Multiple operations on same list

πŸ₯‰ Array-Based Storage

β˜…β˜…β˜…β˜†β˜†

🎯 Understanding recursion

πŸ… Recursive Position Finding

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated