展平链接列表

给定一个链表,其中每个节点代表一个链表,并包含其类型的两个指针: (i) 指向主列表中下一个节点的指针(在下面的代码中我们称之为“右”指针) (ii)指向该节点所在的链表的指针(在下面的代码中,我们称之为“向下”指针)。 所有链接列表都已排序。请参见下面的示例

null
       5 -> 10 -> 19 -> 28       |    |     |     |       V    V     V     V       7    20    22    35       |          |     |       V          V     V       8          50    40       |                |       V                V       30               45

编写一个函数flatte(),将列表展平为单个链接列表。展平的链表也应该进行排序。例如,对于上面的输入列表,输出列表应该是5->7->8->10->19->20->22->28->30->35->40->45->50。

其思想是使用 对链表进行合并排序。 我们使用merge()逐个合并列表。我们递归地将()当前列表与已展平的列表合并。 向下指针用于链接展开列表的节点。

以下是上述方法的实施情况:

C++

// C++ program for flattening a Linked List
#include <bits/stdc++.h>
using namespace std;
// Link list node
class Node
{
public :
int data;
Node *right, *down;
};
Node* head = NULL;
// An utility function to merge two sorted
// linked lists
Node* merge(Node* a, Node* b)
{
// If first linked list is empty then second
// is the answer
if (a == NULL)
return b;
// If second linked list is empty then first
// is the result
if (b == NULL)
return a;
// Compare the data members of the two linked
// lists and put the larger one in the result
Node* result;
if (a->data < b->data)
{
result = a;
result->down = merge(a->down, b);
}
else
{
result = b;
result->down = merge(a, b->down);
}
result->right = NULL;
return result;
}
Node* flatten(Node* root)
{
// Base Cases
if (root == NULL || root->right == NULL)
return root;
// Recur for list on right
root->right = flatten(root->right);
// Now merge
root = merge(root, root->right);
// Return the root
// it will be in turn merged with its left
return root;
}
// Utility function to insert a node at
// beginning of the linked list
Node* push(Node* head_ref, int data)
{
// Allocate the Node & Put in the data
Node* new_node = new Node();
new_node->data = data;
new_node->right = NULL;
// Make next of new Node as head
new_node->down = head_ref;
// Move the head to point to new Node
head_ref = new_node;
return head_ref;
}
void printList()
{
Node* temp = head;
while (temp != NULL)
{
cout << temp->data << " " ;
temp = temp->down;
}
cout << endl;
}
// Driver code
int main()
{
/* Let us create the following linked list
5 -> 10 -> 19 -> 28
|    |     |     |
V    V     V     V
7    20    22    35
|          |     |
V          V     V
8          50    40
|                |
V                V
30               45
*/
head = push(head, 30);
head = push(head, 8);
head = push(head, 7);
head = push(head, 5);
head->right = push(head->right, 20);
head->right = push(head->right, 10);
head->right->right = push(head->right->right, 50);
head->right->right = push(head->right->right, 22);
head->right->right = push(head->right->right, 19);
head->right->right->right = push(head->right->right->right, 45);
head->right->right->right = push(head->right->right->right, 40);
head->right->right->right = push(head->right->right->right, 35);
head->right->right->right = push(head->right->right->right, 20);
// Flatten the list
head = flatten(head);
printList();
return 0;
}
// This code is contributed by rajsanghavi9.


JAVA

// Java program for flattening a Linked List
class LinkedList
{
Node head; // head of list
/* Linked list Node*/
class Node
{
int data;
Node right, down;
Node( int data)
{
this .data = data;
right = null ;
down = null ;
}
}
// An utility function to merge two sorted linked lists
Node merge(Node a, Node b)
{
// if first linked list is empty then second
// is the answer
if (a == null ) return b;
// if second linked list is empty then first
// is the result
if (b == null ) return a;
// compare the data members of the two linked lists
// and put the larger one in the result
Node result;
if (a.data < b.data)
{
result = a;
result.down =  merge(a.down, b);
}
else
{
result = b;
result.down = merge(a, b.down);
}
result.right = null ;
return result;
}
Node flatten(Node root)
{
// Base Cases
if (root == null || root.right == null )
return root;
// recur for list on right
root.right = flatten(root.right);
// now merge
root = merge(root, root.right);
// return the root
// it will be in turn merged with its left
return root;
}
/* Utility function to insert a node at beginning of the
linked list */
Node push(Node head_ref, int data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(data);
/* 3. Make next of new Node as head */
new_node.down = head_ref;
/* 4. Move the head to point to new Node */
head_ref = new_node;
/*5. return to link it back */
return head_ref;
}
void printList()
{
Node temp = head;
while (temp != null )
{
System.out.print(temp.data + " " );
temp = temp.down;
}
System.out.println();
}
/* Driver program to test above functions */
public static void main(String args[])
{
LinkedList L = new LinkedList();
/* Let us create the following linked list
5 -> 10 -> 19 -> 28
|    |     |     |
V    V     V     V
7    20    22    35
|          |     |
V          V     V
8          50    40
|                |
V                V
30               45
*/
L.head = L.push(L.head, 30 );
L.head = L.push(L.head, 8 );
L.head = L.push(L.head, 7 );
L.head = L.push(L.head, 5 );
L.head.right = L.push(L.head.right, 20 );
L.head.right = L.push(L.head.right, 10 );
L.head.right.right = L.push(L.head.right.right, 50 );
L.head.right.right = L.push(L.head.right.right, 22 );
L.head.right.right = L.push(L.head.right.right, 19 );
L.head.right.right.right = L.push(L.head.right.right.right, 45 );
L.head.right.right.right = L.push(L.head.right.right.right, 40 );
L.head.right.right.right = L.push(L.head.right.right.right, 35 );
L.head.right.right.right = L.push(L.head.right.right.right, 20 );
// flatten the list
L.head = L.flatten(L.head);
L.printList();
}
} /* This code is contributed by Rajat Mishra */


Python3

# Python program for flattening a Linked List
class Node():
def __init__( self ,data):
self .data = data
self .right = None
self .down = None
class LinkedList():
def __init__( self ):
# head of list
self .head = None
# Utility function to insert a node at beginning of the
#   linked list
def push( self ,head_ref,data):
# 1 & 2: Allocate the Node &
# Put in the data
new_node = Node(data)
# Make next of new Node as head
new_node.down = head_ref
# 4. Move the head to point to new Node
head_ref = new_node
# 5. return to link it back
return head_ref
def printList( self ):
temp = self .head
while (temp ! = None ):
print (temp.data,end = " " )
temp = temp.down
print ()
# An utility function to merge two sorted linked lists
def merge( self , a, b):
# if first linked list is empty then second
# is the answer
if (a = = None ):
return b
# if second linked list is empty then first
# is the result
if (b = = None ):
return a
# compare the data members of the two linked lists
# and put the larger one in the result
result = None
if (a.data < b.data):
result = a
result.down = self .merge(a.down,b)
else :
result = b
result.down = self .merge(a,b.down)
result.right = None
return result
def flatten( self , root):
# Base Case
if (root = = None or root.right = = None ):
return root
# recur for list on right
root.right = self .flatten(root.right)
# now merge
root = self .merge(root, root.right)
# return the root
# it will be in turn merged with its left
return root
# Driver program to test above functions
L = LinkedList()
'''
Let us create the following linked list
5 -> 10 -> 19 -> 28
|    |     |     |
V    V     V     V
7    20    22    35
|          |     |
V          V     V
8          50    40
|                |
V                V
30               45
'''
L.head = L.push(L.head, 30 );
L.head = L.push(L.head, 8 );
L.head = L.push(L.head, 7 );
L.head = L.push(L.head, 5 );
L.head.right = L.push(L.head.right, 20 );
L.head.right = L.push(L.head.right, 10 );
L.head.right.right = L.push(L.head.right.right, 50 );
L.head.right.right = L.push(L.head.right.right, 22 );
L.head.right.right = L.push(L.head.right.right, 19 );
L.head.right.right.right = L.push(L.head.right.right.right, 45 );
L.head.right.right.right = L.push(L.head.right.right.right, 40 );
L.head.right.right.right = L.push(L.head.right.right.right, 35 );
L.head.right.right.right = L.push(L.head.right.right.right, 20 );
# flatten the list
L.head = L.flatten(L.head);
L.printList()
# This code is contributed by maheshwaripiyush9


C#

// C# program for flattening a Linked List
using System;
public class List {
Node head; // head of list
/* Linked list Node */
public
class Node {
public
int data;
public
Node right, down;
public
Node( int data) {
this .data = data;
right = null ;
down = null ;
}
}
// An utility function to merge two sorted linked lists
Node merge(Node a, Node b) {
// if first linked list is empty then second
// is the answer
if (a == null )
return b;
// if second linked list is empty then first
// is the result
if (b == null )
return a;
// compare the data members of the two linked lists
// and put the larger one in the result
Node result;
if (a.data < b.data) {
result = a;
result.down = merge(a.down, b);
}
else {
result = b;
result.down = merge(a, b.down);
}
result.right = null ;
return result;
}
Node flatten(Node root) {
// Base Cases
if (root == null || root.right == null )
return root;
// recur for list on right
root.right = flatten(root.right);
// now merge
root = merge(root, root.right);
// return the root
// it will be in turn merged with its left
return root;
}
/*
* Utility function to insert a node at beginning of the linked list
*/
Node Push(Node head_ref, int data) {
/*
* 1 & 2: Allocate the Node & Put in the data
*/
Node new_node = new Node(data);
/* 3. Make next of new Node as head */
new_node.down = head_ref;
/* 4. Move the head to point to new Node */
head_ref = new_node;
/* 5. return to link it back */
return head_ref;
}
void printList() {
Node temp = head;
while (temp != null ) {
Console.Write(temp.data + " " );
temp = temp.down;
}
Console.WriteLine();
}
/* Driver program to test above functions */
public static void Main(String []args) {
List L = new List();
/*
* Let us create the following linked list 5 -> 10 -> 19 -> 28 | | | | V V V V 7
* 20 22 35 | | | V V V 8 50 40 | | V V 30 45
*/
L.head = L.Push(L.head, 30);
L.head = L.Push(L.head, 8);
L.head = L.Push(L.head, 7);
L.head = L.Push(L.head, 5);
L.head.right = L.Push(L.head.right, 20);
L.head.right = L.Push(L.head.right, 10);
L.head.right.right = L.Push(L.head.right.right, 50);
L.head.right.right = L.Push(L.head.right.right, 22);
L.head.right.right = L.Push(L.head.right.right, 19);
L.head.right.right.right = L.Push(L.head.right.right.right, 45);
L.head.right.right.right = L.Push(L.head.right.right.right, 40);
L.head.right.right.right = L.Push(L.head.right.right.right, 35);
L.head.right.right.right = L.Push(L.head.right.right.right, 20);
// flatten the list
L.head = L.flatten(L.head);
L.printList();
}
}
// This code is contributed by umadevi9616


Javascript

<script>
// javascript program for flattening a Linked List
var head; // head of list
/* Linked list Node */
class Node {
constructor(val) {
this .data = val;
this .down = null ;
this .next = null ;
}
}
// An utility function to merge two sorted linked lists
function merge(a,  b) {
// if first linked list is empty then second
// is the answer
if (a == null )
return b;
// if second linked list is empty then first
// is the result
if (b == null )
return a;
// compare the data members of the two linked lists
// and put the larger one in the result
var result;
if (a.data < b.data) {
result = a;
result.down = merge(a.down, b);
}
else {
result = b;
result.down = merge(a, b.down);
}
result.right = null ;
return result;
}
function flatten(root) {
// Base Cases
if (root == null || root.right == null )
return root;
// recur for list on right
root.right = flatten(root.right);
// now merge
root = merge(root, root.right);
// return the root
// it will be in turn merged with its left
return root;
}
/*
* Utility function to insert a node at beginning of the linked list
*/
function push(head_ref , data) {
/*
* 1 & 2: Allocate the Node & Put in the data
*/
var new_node = new Node(data);
/* 3. Make next of new Node as head */
new_node.down = head_ref;
/* 4. Move the head to point to new Node */
head_ref = new_node;
/* 5. return to link it back */
return head_ref;
}
function printList() {
var temp = head;
while (temp != null ) {
document.write(temp.data + " " );
temp = temp.down;
}
document.write();
}
/* Driver program to test above functions */
/*
* Let us create the following linked list 5 -> 10 -> 19 -> 28 | | | | V V V V 7
* 20 22 35 | | | V V V 8 50 40 | | V V 30 45
*/
head = push(head, 30);
head = push(head, 8);
head = push(head, 7);
head = push(head, 5);
head.right = push(head.right, 20);
head.right = push(head.right, 10);
head.right.right = push(head.right.right, 50);
head.right.right = push(head.right.right, 22);
head.right.right = push(head.right.right, 19);
head.right.right.right = push(head.right.right.right, 45);
head.right.right.right = push(head.right.right.right, 40);
head.right.right.right = push(head.right.right.right, 35);
head.right.right.right = push(head.right.right.right, 20);
// flatten the list
head = flatten(head);
printList();
// This code contributed by aashish1995
</script>


输出:

5 7 8 10 19 20 20 22 30 35 40 45 50

时间复杂性: O(N*N*M)–其中N是主链表中的节点数(可使用右指针访问),M是单个子链表中的节点数(可使用下指针访问)。

解释: 当我们一次合并两个列表时,

  • 添加前两个列表后,所需时间为O(M+M)=O(2M)。
  • 然后我们将另一个列表合并到上面合并的列表->时间=O(2M+M)=O(3M)。
  • 然后我们将合并另一个列表->时间=O(3M+M)。
  • 我们将继续将列表合并到以前合并的列表,直到所有列表合并。
  • 所需总时间为O(2M+3M+4M+…N*M)=(2+3+4+…+N)*M
  • 使用算术和公式:时间=O((N*N+N-2)*M/2)
  • 上述表达式大致等于 O(N*N*M) 对于N的大值

空间复杂性: O(N*M)——因为递归。递归函数将使用递归堆栈,其大小等于列表中元素的总数,即N*M。

练习: 可以使用优先级队列/min堆优化上述方法。然后时间复杂度为O(N*M*Log(N)),空间复杂度为O(N)。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享