📜  将循环链表拆分为大小几乎相同的三部分

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

将循环链表拆分为大小几乎相同的三部分

在不计算长度的情况下将给定的循环链表拆分为三部分,使得具有最大节点数的链表与具有最小节点数的链表之间的差异最小。

例子

方法:解决这个问题的方法是使用龟兔算法。

  • 将慢速、平均和快速指针移动 1、2 和 3
  • 当快速指针到达 NULL 时,avg 指针到达后半部分的末尾,慢速指针到达前半部分的末尾。
  • 使第三个半圆形。
  • 将下半部分做成圆形。
  • 将前半部分做成圆形。
  • 设置两个链表的头指针

下面是上述方法的实现:

C++
// Program to split a circular linked list
// into three halves
#include 
using namespace std;
 
/* structure for a node */
class Node {
public:
    int data;
    Node* next;
};
 
// Function to split a list
// (starting with head) into three lists.
// head1_ref, head2_ref & head3_ref are
// references to head nodes of the
// three resultant linked lists
void splitList(Node* head, Node** head1_ref,
               Node** head2_ref,
               Node** head3_ref)
{
    Node* slow_ptr = head;
    Node* avg_ptr = head->next;
    Node* fast_ptr = head->next->next;
 
    if (head == NULL
        || head->next == NULL
        || head->next->next == NULL)
        return;
 
    while (fast_ptr->next != head
           && fast_ptr->next->next != head) {
 
        if (fast_ptr->next->next->next
            != head)
            fast_ptr
                = fast_ptr->next->next->next;
        else {
            fast_ptr = fast_ptr->next->next;
        }
        avg_ptr = avg_ptr->next->next;
        slow_ptr = slow_ptr->next;
    }
 
    while (fast_ptr->next != head)
        fast_ptr = fast_ptr->next;
 
    // Make third half circular
    *head3_ref = avg_ptr->next;
    fast_ptr->next = *head3_ref;
 
    // Make second half circular
    *head2_ref = slow_ptr->next;
    avg_ptr->next = *head2_ref;
 
    // Make first half circular
    *head1_ref = head;
    slow_ptr->next = *head1_ref;
}
 
// Function to insert a node at
// the beginning of a Circular linked list
void push(Node** head_ref, int data)
{
    Node* ptr1 = new Node();
    Node* temp = *head_ref;
    ptr1->data = data;
    ptr1->next = *head_ref;
 
    // If linked list is not NULL then
    // set the next of last node
    if (*head_ref != NULL) {
        while (temp->next != *head_ref)
            temp = temp->next;
        temp->next = ptr1;
    }
    else
        // For the first node
        ptr1->next = ptr1;
 
    *head_ref = ptr1;
}
 
// Function to print nodes in
// a given Circular linked list
void printList(Node* head)
{
    Node* temp = head;
    if (head != NULL) {
        do {
            cout << temp->data << " ";
            temp = temp->next;
        } while (temp != head);
    }
    cout << endl;
}
 
// Driver Code
int main()
{
    int list_size, i;
 
    // Initialize lists as empty
    Node* head = NULL;
    Node* head1 = NULL;
    Node* head2 = NULL;
    Node* head3 = NULL;
 
    // Created linked list will be
    // 1->3->5->7->9
    push(&head, 1);
    push(&head, 3);
    push(&head, 5);
    push(&head, 7);
    push(&head, 9);
 
    // Split the list
    splitList(head, &head1, &head2, &head3);
 
    // First Circular Linked List
    printList(head1);
 
    // Second Circular Linked List
    printList(head2);
 
    // Third Circular Linked List
    printList(head3);
 
    return 0;
}


Java
// Program to split a circular linked list
// into three halves
import java.util.*;
class GFG{
 
  /* structure for a node */
  static class Node {
 
    int data;
    Node next;
  };
 
  // Function to split a list
  // (starting with head) into three lists.
  // head1_ref, head2_ref & head3_ref are
  // references to head nodes of the
  // three resultant linked lists
 
  static Node head1_ref;
  static Node head2_ref;
  static Node head3_ref;
  static void splitList(Node head)
  {
    Node slow_ptr = head;
    Node avg_ptr = head.next;
    Node fast_ptr = head.next.next;
 
    if (head == null
        || head.next == null
        || head.next.next == null)
      return;
 
    while (fast_ptr.next != head
           && fast_ptr.next.next != head) {
 
      if (fast_ptr.next.next.next
          != head)
        fast_ptr
        = fast_ptr.next.next.next;
      else {
        fast_ptr = fast_ptr.next.next;
      }
      avg_ptr = avg_ptr.next.next;
      slow_ptr = slow_ptr.next;
    }
 
    while (fast_ptr.next != head)
      fast_ptr = fast_ptr.next;
 
    // Make third half circular
    head3_ref = avg_ptr.next;
    fast_ptr.next = head3_ref;
 
    // Make second half circular
    head2_ref = slow_ptr.next;
    avg_ptr.next = head2_ref;
 
    // Make first half circular
    head1_ref = head;
    slow_ptr.next = head1_ref;
  }
 
  // Function to insert a node at
  // the beginning of a Circular linked list
  static Node push(Node head_ref, int data)
  {
    Node ptr1 = new Node();
    Node temp = head_ref;
    ptr1.data = data;
    ptr1.next = head_ref;
 
    // If linked list is not null then
    // set the next of last node
    if (head_ref != null) {
      while (temp.next != head_ref)
        temp = temp.next;
      temp.next = ptr1;
    }
    else
      // For the first node
      ptr1.next = ptr1;
 
    head_ref = ptr1;
    return head_ref;
  }
 
  // Function to print nodes in
  // a given Circular linked list
  static void printList(Node head)
  {
    Node temp = head;
    if (head != null) {
      do {
        System.out.print(temp.data+ " ");
        temp = temp.next;
      } while (temp != head);
    }
    System.out.println();
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int list_size, i;
 
    // Initialize lists as empty
    Node head = null;
    head1_ref = null;
    head2_ref = null;
    head3_ref = null;
 
    // Created linked list will be
    // 1.3.5.7.9
    head = push(head, 1);
    head = push(head, 3);
    head = push(head, 5);
    head = push(head, 7);
    head = push(head, 9);
 
    // Split the list
    splitList(head);
 
    // First Circular Linked List
    printList(head1_ref);
 
    // Second Circular Linked List
    printList(head2_ref);
 
    // Third Circular Linked List
    printList(head3_ref);
  }
}
 
// This code is contributed by shikhasingrajput



输出:
9 7 
5 3 
1

时间复杂度:O(N)
辅助空间:O(1)