📌  相关文章
📜  在链表中从头开始交换第 K 个节点与从末尾开始的第 K 个节点

📅  最后修改于: 2022-05-13 01:57:46.077000             🧑  作者: Mango

在链表中从头开始交换第 K 个节点与从末尾开始的第 K 个节点

给定一个单向链表,从头开始交换第 k 个节点和从末尾开始的第 k 个节点。不允许交换数据,只应更改指针。在链表数据部分很大的许多情况下,这个要求可能是合乎逻辑的(例如学生详细信息行 Name、RollNo、Address 等)。指针总是固定的(大多数编译器为 4 个字节)。
例子:

Input: 1 -> 2 -> 3 -> 4 -> 5, K = 2
Output: 1 -> 4 -> 3 -> 2 -> 5 
Explanation: The 2nd node from 1st is 2 and 
2nd node from last is 4, so swap them.


Input: 1 -> 2 -> 3 -> 4 -> 5, K = 5
Output: 5 -> 2 -> 3 -> 4 -> 1 
Explanation: The 5th node from 1st is 5 and 
5th node from last is 1, so swap them.

插图:

方法:这个想法很简单,从头开始找到第k个节点,最后的第k个节点是从头开始的第n-k+1个节点。交换两个节点。
但是有一些极端情况,必须处理



  1. Y 在 X 旁边
  2. X 在 Y 旁边
  3. X 和 Y 相同
  4. X 和 Y 不存在(k 大于链表中的节点数)

下面是上述方法的实现。

C++
// A C++ program to swap Kth node
// from beginning with kth node from end
#include 
using namespace std;
 
// A Linked List node
struct Node {
    int data;
    struct Node* next;
};
 
/* Utility function to insert
   a node at the beginning */
void push(struct Node** head_ref, int new_data)
{
    struct Node* new_node
        = (struct Node*)malloc(
            sizeof(struct Node));
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}
 
/* Utility function for displaying linked list */
void printList(struct Node* node)
{
    while (node != NULL) {
        cout << node->data << " ";
        node = node->next;
    }
    cout << endl;
}
 
/* Utility function for calculating
   length of linked list */
int countNodes(struct Node* s)
{
    int count = 0;
    while (s != NULL) {
        count++;
        s = s->next;
    }
    return count;
}
 
/* Function for swapping kth nodes
   from both ends of linked list */
void swapKth(struct Node** head_ref, int k)
{
    // Count nodes in linked list
    int n = countNodes(*head_ref);
 
    // Check if k is valid
    if (n < k)
        return;
 
    // If x (kth node from start) and
    // y(kth node from end) are same
    if (2 * k - 1 == n)
        return;
 
    // Find the kth node from the beginning of
    // the linked list. We also find
    // previous of kth node because we
    // need to update next pointer of
    // the previous.
    Node* x = *head_ref;
    Node* 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
    Node* y = *head_ref;
    Node* 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.
    if (x_prev)
        x_prev->next = y;
 
    // Same thing applies to y_prev
    if (y_prev)
        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
    Node* temp = x->next;
    x->next = y->next;
    y->next = temp;
 
    // Change head pointers when k is 1 or n
    if (k == 1)
        *head_ref = y;
    if (k == n)
        *head_ref = x;
}
 
// Driver program to test above functions
int main()
{
    // Let us create the following
    // linked list for testing
    // 1->2->3->4->5->6->7->8
    struct Node* head = NULL;
    for (int i = 8; i >= 1; i--)
        push(&head, i);
 
    cout << "Original Linked List: ";
    printList(head);
 
    for (int k = 1; k < 9; k++) {
        swapKth(&head, k);
        cout << "\nModified List for k = " << k << endl;
        printList(head);
    }
 
    return 0;
}


Java
// A Java program to swap kth
// node from the beginning with
// kth node from the end
 
class Node {
    int data;
    Node next;
    Node(int d)
    {
        data = d;
        next = null;
    }
}
 
class LinkedList {
    Node head;
 
    /* Utility function to insert
       a node at the beginning */
    void push(int new_data)
    {
        Node new_node = new Node(new_data);
        new_node.next = head;
        head = new_node;
    }
 
    /* Utility function for displaying linked list */
    void printList()
    {
        Node node = head;
        while (node != null) {
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println("");
    }
 
    /* Utility function for calculating
       length of linked list */
    int countNodes()
    {
        int count = 0;
        Node s = head;
        while (s != null) {
            count++;
            s = s.next;
        }
        return count;
    }
 
    /* Function for swapping kth nodes from
       both ends of linked list */
    void swapKth(int k)
    {
        // Count nodes in linked list
        int n = countNodes();
 
        // Check if k is valid
        if (n < k)
            return;
 
        // If x (kth node from start) and
        // y(kth node from end) are same
        if (2 * k - 1 == n)
            return;
 
        // 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.
        Node x = head;
        Node 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
        Node y = head;
        Node 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.
        if (x_prev != null)
            x_prev.next = y;
 
        // Same thing applies to y_prev
        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
        Node temp = x.next;
        x.next = y.next;
        y.next = temp;
 
        // Change head pointers when k is 1 or n
        if (k == 1)
            head = y;
 
        if (k == n)
            head = x;
    }
 
    // Driver code to test above
    public static void main(String[] args)
    {
        LinkedList llist = new LinkedList();
        for (int i = 8; i >= 1; i--)
            llist.push(i);
 
        System.out.print("Original linked list: ");
        llist.printList();
        System.out.println("");
 
        for (int i = 1; i < 9; i++) {
            llist.swapKth(i);
            System.out.println("Modified List for k = " + i);
            llist.printList();
            System.out.println("");
        }
    }
}


Python3
"""
A Python3 program to swap kth node from
the beginning with kth node from the end
"""
class Node:
    def __init__(self, data, next = None):
        self.data = data
        self.next = next
     
class LinkedList:
 
    def __init__(self, *args, **kwargs):
        self.head = Node(None)
    """
    Utility function to insert a node at the beginning
    @args:
        data: value of node
    """
    def push(self, data):
        node = Node(data)
        node.next = self.head
        self.head = node
     
    # Print linked list
    def printList(self):
        node = self.head
        while node.next is not None:
            print(node.data, end = " ")
            node = node.next
     
    # count number of node in linked list
    def countNodes(self):
        count = 0
        node = self.head
        while node.next is not None:
            count += 1
            node = node.next
        return count
     
    """
    Function for swapping kth nodes from
    both ends of linked list
    """
    def swapKth(self, k):
 
        # Count nodes in linked list
        n = self.countNodes()
 
        # check if k is valid
        if nnext 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.
        """
        if x_prev is not None:
            x_prev.next = y
 
        # Same thing applies to y_prev
        if y_prev is not None:
            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
        """
        temp = x.next
        x.next = y.next
        y.next = temp
 
        # Change head pointers when k is 1 or n
        if k == 1:
            self.head = y
         
        if k == n:
            self.head = x
 
# Driver Code
llist = LinkedList()
for i in range(8, 0, -1):
    llist.push(i)
llist.printList()
 
 
for i in range(1, 9):
    llist.swapKth(i)
    print("Modified List for k = ", i)
    llist.printList()
    print("\n")
 
# This code is contributed by Pulkit


C#
// C# program to swap kth node from the beginning with
// kth node from the end
using System;
 
public class Node {
    public int data;
    public Node next;
    public Node(int d)
    {
        data = d;
        next = null;
    }
}
 
public class LinkedList {
    Node head;
 
    /* Utility function to insert
    a node at the beginning */
    void push(int new_data)
    {
        Node new_node = new Node(new_data);
        new_node.next = head;
        head = new_node;
    }
 
    /* Utility function for displaying linked list */
    void printList()
    {
        Node node = head;
        while (node != null) {
            Console.Write(node.data + " ");
            node = node.next;
        }
        Console.WriteLine("");
    }
 
    /* Utility function for calculating
    length of linked list */
    int countNodes()
    {
        int count = 0;
        Node s = head;
        while (s != null) {
            count++;
            s = s.next;
        }
        return count;
    }
 
    /* Function for swapping kth nodes from
    both ends of linked list */
    void swapKth(int k)
    {
        // Count nodes in linked list
        int n = countNodes();
 
        // Check if k is valid
        if (n < k)
            return;
 
        // If x (kth node from start) and y(kth node from end)
        // are same
        if (2 * k - 1 == n)
            return;
 
        // 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.
        Node x = head;
        Node 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
        Node y = head;
        Node 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.
        if (x_prev != null)
            x_prev.next = y;
 
        // Same thing applies to y_prev
        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
        Node temp = x.next;
        x.next = y.next;
        y.next = temp;
 
        // Change head pointers when k is 1 or n
        if (k == 1)
            head = y;
 
        if (k == n)
            head = x;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        LinkedList llist = new LinkedList();
        for (int i = 8; i >= 1; i--)
            llist.push(i);
 
        Console.Write("Original linked list: ");
        llist.printList();
        Console.WriteLine("");
 
        for (int i = 1; i < 9; i++) {
            llist.swapKth(i);
            Console.WriteLine("Modified List for k = " + i);
            llist.printList();
            Console.WriteLine("");
        }
    }
}
 
// This code has been contributed by 29AjayKumar


Javascript


输出:

Original Linked List: 1 2 3 4 5 6 7 8

Modified List for k = 1
8 2 3 4 5 6 7 1

Modified List for k = 2
8 7 3 4 5 6 2 1

Modified List for k = 3
8 7 6 4 5 3 2 1

Modified List for k = 4
8 7 6 5 4 3 2 1

Modified List for k = 5
8 7 6 4 5 3 2 1

Modified List for k = 6
8 7 3 4 5 6 2 1

Modified List for k = 7
8 2 3 4 5 6 7 1

Modified List for k = 8
1 2 3 4 5 6 7 8

复杂度分析:

  • 时间复杂度: O(n),其中 n 是列表的长度。
    需要对列表进行一次遍历。
  • 辅助空间: O(1)。
    不需要额外的空间。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程