将元素转换为正方形后对链表进行排序
给定一个非递减链表。任务是将链表的元素平方并按排序顺序排列它们,而不使用任何额外的空间。
例子:
Input: 1->2->3->4->5
Output: 1->4->9->16->25
Input: (-2) -> (-1) -> 0 -> 1 -> 2
Output: 0 ->1 -> 1 -> 4 -> 4
对于数组:本文讨论了对数组执行相同操作的问题——将元素转换为正方形后对数组进行排序
方法:可以通过将给定列表从转换点(负到正)划分为两个不同的链表来解决该任务,一个仅包含负元素的链表为“ 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)