📌  相关文章
📜  将元素转换为正方形后对链表进行排序

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

将元素转换为正方形后对链表进行排序

给定一个非递减链表。任务是将链表的元素平方并按排序顺序排列它们,而不使用任何额外的空间。

例子

对于数组:本文讨论了对数组执行相同操作的问题——将元素转换为正方形后对数组进行排序

方法:可以通过将给定列表从转换点(负到正)划分为两个不同的链表来解决该任务,一个仅包含负元素的链表为“ l1 ”,另一个包含正元素的链表为“ l2 ”。将列表l1的所有元素平方并反转它,并将列表l2 的所有元素平方,现在合并两个排序列表以获得结果列表。

以下是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
struct Node {
    int data;
    Node* next;
    Node(int data)
    {
        this->data = data;
        this->next = NULL;
    }
};
 
// Utility function to make linked list
Node* makeList(int n, int arr[])
{
    Node* h = NULL;
    Node* root;
    for (int i = 0; i < n; i++) {
        int data = arr[i];
 
        Node* node = new Node(data);
 
        if (h == NULL) {
            h = node;
            root = h;
        }
        else {
            root->next = node;
            root = node;
        }
    }
    return h;
}
 
// Utility function to print list
void print_list(Node* head)
{
    while (head != NULL) {
        cout << head->data << " ";
        head = head->next;
    }
    cout << "\n";
}
 
// Function to reverse the linked list
Node* reverse(Node* head)
{
    // Initialize current, previous and
    // next pointers
    Node* current = head;
    Node *prev = NULL, *next = NULL;
 
    while (current != NULL) {
        // Store next
        next = current->next;
 
        // Reverse current node's pointer
        current->next = prev;
 
        // Move pointers one position ahead.
        prev = current;
        current = next;
    }
    head = prev;
    return head;
}
 
// This function will find the point of transition
// where elements switch from negative to positive
// and return that point
Node* findBreakPoint(Node* head)
{
    if (head == NULL) {
        return NULL;
    }
 
    Node *prev = NULL, *curr = head;
 
    while (curr != NULL) {
        prev = curr;
        curr = curr->next;
 
        if (curr != NULL) {
            // If prev element is negative and
            // current element is positive
            if ((prev->data) < 0
                and (curr->data) >= 0) {
 
                return prev;
            }
        }
    }
 
    // Checking if list contains
    // only negative elements
    curr = head;
    while (curr->next) {
        if (curr->data < 0) {
            curr = curr->next;
            continue;
        }
        else {
            // Contains positive elements
            return NULL;
        }
    }
 
    // Contains only negative element
    // so returning the last element of the list
    return curr;
}
 
// Utility function to merge two sorted lists
struct Node* mergeUtil(struct Node* h1,
                       struct Node* h2)
{
    // If only one node in first list
    // simply point its head to second list
    if (!h1->next) {
        h1->next = h2;
        return h1;
    }
 
    // Initialize current and next pointers of
    // both lists
    struct Node *curr1 = h1, *next1 = h1->next;
    struct Node *curr2 = h2, *next2 = h2->next;
 
    while (next1 && curr2) {
        // If curr2 lies in between
        // curr1 and next1
        // then do curr1->curr2->next1
        if ((curr2->data) >= (curr1->data)
            && (curr2->data) <= (next1->data)) {
            next2 = curr2->next;
            curr1->next = curr2;
            curr2->next = next1;
 
            // Let curr1 and curr2 to point
            // their immediate next pointers
            curr1 = curr2;
            curr2 = next2;
        }
        else {
            // If more nodes in first list
            if (next1->next) {
                next1 = next1->next;
                curr1 = curr1->next;
            }
 
            // Else point the last
            // node of first list
            // to the remaining
            // nodes of second list
            else {
                next1->next = curr2;
                return h1;
            }
        }
    }
    return h1;
}
 
// Merges two given lists in-place.
// This function mainly compares
// head nodes and calls mergeUtil()
struct Node* merge(struct Node* h1,
                   struct Node* h2)
{
    if (!h1)
        return h2;
    if (!h2)
        return h1;
 
    // Start with the linked list
    // whose head data is the least
    if (h1->data < h2->data)
        return mergeUtil(h1, h2);
    else
        return mergeUtil(h2, h1);
}
 
// Function to return resultant squared list
Node* squaresList(Node* head)
{
    if (head == NULL)
        return NULL;
 
    Node* mid = findBreakPoint(head);
 
    Node* temp = head;
    while (temp != NULL) {
        temp->data *= temp->data;
        temp = temp->next;
    }
 
    // List contains only positive elements
    if (mid == NULL) {
        return head;
    }
 
    // List contains both positive
    // and negative elements
    Node* h1 = head;
    Node* h2 = mid->next;
 
    // Breaking the list where negative
    // switches to positive
    mid->next = NULL;
 
    // Reversing the list
    h1 = reverse(h1);
 
    // Merging the two lists
    Node* ans = merge(h1, h2);
 
    return ans;
}
 
// Driver Program
int main()
{
 
    int n = 7;
    int arr1[] = { 1, 2, 3, 4, 5 };
    Node* head = makeList(sizeof(arr1)
                              / sizeof(int),
                          arr1);
 
    n = 6;
    int arr2[] = { -2, -1, 0, 1, 2 };
    head = makeList(sizeof(arr2)
                        / sizeof(int),
                    arr2);
 
    int arr3[] = { -5, -4, -3, -2, -1 };
    head = makeList(sizeof(arr3)
                        / sizeof(int),
                    arr3);
    print_list(squaresList(head));
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
static class Node {
    int data;
    Node next;
    Node(int data)
    {
        this.data = data;
        this.next = null;
    }
    public Node() {
        // TODO Auto-generated constructor stub
    }
};
 
// Utility function to make linked list
static Node makeList(int n, int arr[])
{
    Node h = null;
    Node root = new Node();
    for (int i = 0; i < n; i++) {
        int data = arr[i];
 
        Node node = new Node(data);
 
        if (h == null) {
            h = node;
            root = h;
        }
        else {
            root.next = node;
            root = node;
        }
    }
    return h;
}
 
// Utility function to print list
static void print_list(Node head)
{
    while (head != null) {
        System.out.print(head.data+ " ");
        head = head.next;
    }
    System.out.print("\n");
}
 
// Function to reverse the linked list
static Node reverse(Node head)
{
    // Initialize current, previous and
    // next pointers
    Node current = head;
    Node prev = null, next = null;
 
    while (current != null) {
        // Store next
        next = current.next;
 
        // Reverse current node's pointer
        current.next = prev;
 
        // Move pointers one position ahead.
        prev = current;
        current = next;
    }
    head = prev;
    return head;
}
 
// This function will find the point of transition
// where elements switch from negative to positive
// and return that point
static Node findBreakPoint(Node head)
{
    if (head == null) {
        return null;
    }
 
    Node prev = null, curr = head;
 
    while (curr != null) {
        prev = curr;
        curr = curr.next;
 
        if (curr != null) {
            // If prev element is negative and
            // current element is positive
            if ((prev.data) < 0
                && (curr.data) >= 0) {
 
                return prev;
            }
        }
    }
 
    // Checking if list contains
    // only negative elements
    curr = head;
    while (curr.next!=null) {
        if (curr.data < 0) {
            curr = curr.next;
            continue;
        }
        else {
            // Contains positive elements
            return null;
        }
    }
 
    // Contains only negative element
    // so returning the last element of the list
    return curr;
}
 
// Utility function to merge two sorted lists
static Node mergeUtil(Node h1,
                       Node h2)
{
    // If only one node in first list
    // simply point its head to second list
    if (h1.next!=null) {
        h1.next = h2;
        return h1;
    }
 
    // Initialize current and next pointers of
    // both lists
    Node curr1 = h1, next1 = h1.next;
    Node curr2 = h2, next2 = h2.next;
 
    while (next1!=null && curr2!=null) {
        // If curr2 lies in between
        // curr1 and next1
        // then do curr1.curr2.next1
        if ((curr2.data) >= (curr1.data)
            && (curr2.data) <= (next1.data)) {
            next2 = curr2.next;
            curr1.next = curr2;
            curr2.next = next1;
 
            // Let curr1 and curr2 to point
            // their immediate next pointers
            curr1 = curr2;
            curr2 = next2;
        }
        else {
            // If more nodes in first list
            if (next1.next!=null) {
                next1 = next1.next;
                curr1 = curr1.next;
            }
 
            // Else point the last
            // node of first list
            // to the remaining
            // nodes of second list
            else {
                next1.next = curr2;
                return h1;
            }
        }
    }
    return h1;
}
 
// Merges two given lists in-place.
// This function mainly compares
// head nodes and calls mergeUtil()
static Node merge(Node h1,
                   Node h2)
{
    if (h1==null)
        return h2;
    if (h2==null)
        return h1;
 
    // Start with the linked list
    // whose head data is the least
    if (h1.data < h2.data)
        return mergeUtil(h1, h2);
    else
        return mergeUtil(h2, h1);
}
 
// Function to return resultant squared list
static Node squaresList(Node head)
{
    if (head == null)
        return null;
 
    Node mid = findBreakPoint(head);
 
    Node temp = head;
    while (temp != null) {
        temp.data *= temp.data;
        temp = temp.next;
    }
 
    // List contains only positive elements
    if (mid == null) {
        return head;
    }
 
    // List contains both positive
    // and negative elements
    Node h1 = head;
    Node h2 = mid.next;
 
    // Breaking the list where negative
    // switches to positive
    mid.next = null;
 
    // Reversing the list
    h1 = reverse(h1);
 
    // Merging the two lists
    Node ans = merge(h1, h2);
 
    return ans;
}
 
// Driver Program
public static void main(String[] args)
{
 
    int n = 7;
    int arr1[] = { 1, 2, 3, 4, 5 };
    Node head = makeList(arr1.length,
                          arr1);
 
    n = 6;
    int arr2[] = { -2, -1, 0, 1, 2 };
    head = makeList(arr2.length,
                    arr2);
 
    int arr3[] = { -5, -4, -3, -2, -1 };
    head = makeList(arr3.length,
                    arr3);
    print_list(squaresList(head));
}
}
 
// This code is contributed by 29AjayKumar


C#
// C# program for the above approach
using System;
 
public class GFG{
 
class Node {
    public int data;
    public Node next;
    public Node(int data)
    {
        this.data = data;
        this.next = null;
    }
    public Node() {
        // TODO Auto-generated constructor stub
    }
};
 
// Utility function to make linked list
static Node makeList(int n, int []arr)
{
    Node h = null;
    Node root = new Node();
    for (int i = 0; i < n; i++) {
        int data = arr[i];
 
        Node node = new Node(data);
 
        if (h == null) {
            h = node;
            root = h;
        }
        else {
            root.next = node;
            root = node;
        }
    }
    return h;
}
 
// Utility function to print list
static void print_list(Node head)
{
    while (head != null) {
        Console.Write(head.data+ " ");
        head = head.next;
    }
    Console.Write("\n");
}
 
// Function to reverse the linked list
static Node reverse(Node head)
{
    // Initialize current, previous and
    // next pointers
    Node current = head;
    Node prev = null, next = null;
 
    while (current != null) {
        // Store next
        next = current.next;
 
        // Reverse current node's pointer
        current.next = prev;
 
        // Move pointers one position ahead.
        prev = current;
        current = next;
    }
    head = prev;
    return head;
}
 
// This function will find the point of transition
// where elements switch from negative to positive
// and return that point
static Node findBreakPoint(Node head)
{
    if (head == null) {
        return null;
    }
 
    Node prev = null, curr = head;
 
    while (curr != null) {
        prev = curr;
        curr = curr.next;
 
        if (curr != null) {
            // If prev element is negative and
            // current element is positive
            if ((prev.data) < 0
                && (curr.data) >= 0) {
 
                return prev;
            }
        }
    }
 
    // Checking if list contains
    // only negative elements
    curr = head;
    while (curr.next!=null) {
        if (curr.data < 0) {
            curr = curr.next;
            continue;
        }
        else {
            // Contains positive elements
            return null;
        }
    }
 
    // Contains only negative element
    // so returning the last element of the list
    return curr;
}
 
// Utility function to merge two sorted lists
static Node mergeUtil(Node h1,
                       Node h2)
{
    // If only one node in first list
    // simply point its head to second list
    if (h1.next!=null) {
        h1.next = h2;
        return h1;
    }
 
    // Initialize current and next pointers of
    // both lists
    Node curr1 = h1, next1 = h1.next;
    Node curr2 = h2, next2 = h2.next;
 
    while (next1!=null && curr2!=null) {
        // If curr2 lies in between
        // curr1 and next1
        // then do curr1.curr2.next1
        if ((curr2.data) >= (curr1.data)
            && (curr2.data) <= (next1.data)) {
            next2 = curr2.next;
            curr1.next = curr2;
            curr2.next = next1;
 
            // Let curr1 and curr2 to point
            // their immediate next pointers
            curr1 = curr2;
            curr2 = next2;
        }
        else {
            // If more nodes in first list
            if (next1.next!=null) {
                next1 = next1.next;
                curr1 = curr1.next;
            }
 
            // Else point the last
            // node of first list
            // to the remaining
            // nodes of second list
            else {
                next1.next = curr2;
                return h1;
            }
        }
    }
    return h1;
}
 
// Merges two given lists in-place.
// This function mainly compares
// head nodes and calls mergeUtil()
static Node merge(Node h1,
                   Node h2)
{
    if (h1==null)
        return h2;
    if (h2==null)
        return h1;
 
    // Start with the linked list
    // whose head data is the least
    if (h1.data < h2.data)
        return mergeUtil(h1, h2);
    else
        return mergeUtil(h2, h1);
}
 
// Function to return resultant squared list
static Node squaresList(Node head)
{
    if (head == null)
        return null;
 
    Node mid = findBreakPoint(head);
 
    Node temp = head;
    while (temp != null) {
        temp.data *= temp.data;
        temp = temp.next;
    }
 
    // List contains only positive elements
    if (mid == null) {
        return head;
    }
 
    // List contains both positive
    // and negative elements
    Node h1 = head;
    Node h2 = mid.next;
 
    // Breaking the list where negative
    // switches to positive
    mid.next = null;
 
    // Reversing the list
    h1 = reverse(h1);
 
    // Merging the two lists
    Node ans = merge(h1, h2);
 
    return ans;
}
 
// Driver Program
public static void Main(String[] args)
{
 
    int n = 7;
    int []arr1 = { 1, 2, 3, 4, 5 };
    Node head = makeList(arr1.Length,
                          arr1);
 
    n = 6;
    int []arr2 = { -2, -1, 0, 1, 2 };
    head = makeList(arr2.Length,
                    arr2);
 
    int []arr3 = { -5, -4, -3, -2, -1 };
    head = makeList(arr3.Length,
                    arr3);
    print_list(squaresList(head));
}
}
 
// This code is contributed by 29AjayKumar


Javascript


输出
1 4 9 16 25 

时间复杂度:O(N),N是节点数
辅助空间:O(1)