本文概述
给定两个链表, 创建包含给定列表中元素的并集和交集的并集和交集列表。输出列表中元素的顺序无关紧要。
例子:
Input:
List1: 10->15->4->20
lsit2: 8->4->2->10
Output:
Intersection List: 4->10
Union List: 2->8->20->4->15->10
推荐:请在"实践首先, 在继续解决方案之前。
方法1(简单)
以下是分别获取联合和相交列表的简单算法。
交叉点(列表1, 列表2)
将结果列表初始化为NULL。遍历list1并在list2中查找其每个元素, 如果list2中存在该元素, 则将其添加到结果中。
联合(list1, list2):
将结果列表初始化为NULL。遍历list1并将其所有元素添加到结果中。
遍历列表2。如果结果中已经存在list2元素, 则不要将其插入到result中, 否则插入。
此方法假定给定列表中没有重复项。
感谢Shekhu建议这种方法。以下是此方法的C和Java实现。
C / C ++
// C/C++ program to find union
// and intersection of two unsorted
// linked lists
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* Link list node */
struct Node {
int data;
struct Node* next;
};
/* A utility function to insert a
node at the beginning ofa linked list*/
void push( struct Node** head_ref, int new_data);
/* A utility function to check if
given data is present in a list */
bool isPresent( struct Node* head, int data);
/* Function to get union of two
linked lists head1 and head2 */
struct Node* getUnion(
struct Node* head1, struct Node* head2)
{
struct Node* result = NULL;
struct Node *t1 = head1, *t2 = head2;
// Insert all elements of
// list1 to the result list
while (t1 != NULL) {
push(&result, t1->data);
t1 = t1->next;
}
// Insert those elements of list2
// which are not present in result list
while (t2 != NULL) {
if (!isPresent(result, t2->data))
push(&result, t2->data);
t2 = t2->next;
}
return result;
}
/* Function to get intersection of
two linked lists head1 and head2 */
struct Node* getIntersection( struct Node* head1, struct Node* head2)
{
struct Node* result = NULL;
struct Node* t1 = head1;
// Traverse list1 and search each element of it in
// list2. If the element is present in list 2, then
// insert the element to result
while (t1 != NULL) {
if (isPresent(head2, t1->data))
push(&result, t1->data);
t1 = t1->next;
}
return result;
}
/* A utility function to insert a
node at the beginning of a linked list*/
void push( struct Node** head_ref, int new_data)
{
/* allocate node */
struct Node* new_node
= ( struct Node*) malloc (
sizeof ( struct Node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print a linked list*/
void printList( struct Node* node)
{
while (node != NULL) {
printf ( "%d " , node->data);
node = node->next;
}
}
/* A utility function that returns true if data is
present in linked list else return false */
bool isPresent( struct Node* head, int data)
{
struct Node* t = head;
while (t != NULL) {
if (t->data == data)
return 1;
t = t->next;
}
return 0;
}
/* Driver program to test above function*/
int main()
{
/* Start with the empty list */
struct Node* head1 = NULL;
struct Node* head2 = NULL;
struct Node* intersecn = NULL;
struct Node* unin = NULL;
/*create a linked lits 10->15->5->20 */
push(&head1, 20);
push(&head1, 4);
push(&head1, 15);
push(&head1, 10);
/*create a linked lits 8->4->2->10 */
push(&head2, 10);
push(&head2, 2);
push(&head2, 4);
push(&head2, 8);
intersecn = getIntersection(head1, head2);
unin = getUnion(head1, head2);
printf ( "\n First list is \n" );
printList(head1);
printf ( "\n Second list is \n" );
printList(head2);
printf ( "\n Intersection list is \n" );
printList(intersecn);
printf ( "\n Union list is \n" );
printList(unin);
return 0;
}
Java
// Java program to find union and
// intersection of two unsorted
// linked lists
class LinkedList {
Node head; // head of list
/* Linked list Node*/
class Node {
int data;
Node next;
Node( int d)
{
data = d;
next = null ;
}
}
/* Function to get Union of 2 Linked Lists */
void getUnion(Node head1, Node head2)
{
Node t1 = head1, t2 = head2;
// insert all elements of list1 in the result
while (t1 != null ) {
push(t1.data);
t1 = t1.next;
}
// insert those elements of list2
// that are not present
while (t2 != null ) {
if (!isPresent(head, t2.data))
push(t2.data);
t2 = t2.next;
}
}
void getIntersection(Node head1, Node head2)
{
Node result = null ;
Node t1 = head1;
// Traverse list1 and search each
// element of it in list2.
// If the element is present in
// list 2, then insert the
// element to result
while (t1 != null ) {
if (isPresent(head2, t1.data))
push(t1.data);
t1 = t1.next;
}
}
/* Utility function to print list */
void printList()
{
Node temp = head;
while (temp != null ) {
System.out.print(temp.data + " " );
temp = temp.next;
}
System.out.println();
}
/* Inserts a node at start of linked list */
void push( int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.next = head;
/* 4. Move the head to point to new Node */
head = new_node;
}
/* A utilty function that returns true
if data is present in linked list
else return false */
boolean isPresent(Node head, int data)
{
Node t = head;
while (t != null ) {
if (t.data == data)
return true ;
t = t.next;
}
return false ;
}
/* Driver program to test above functions */
public static void main(String args[])
{
LinkedList llist1 = new LinkedList();
LinkedList llist2 = new LinkedList();
LinkedList unin = new LinkedList();
LinkedList intersecn = new LinkedList();
/*create a linked lits 10->15->5->20 */
llist1.push( 20 );
llist1.push( 4 );
llist1.push( 15 );
llist1.push( 10 );
/*create a linked lits 8->4->2->10 */
llist2.push( 10 );
llist2.push( 2 );
llist2.push( 4 );
llist2.push( 8 );
intersecn.getIntersection(llist1.head, llist2.head);
unin.getUnion(llist1.head, llist2.head);
System.out.println( "First List is" );
llist1.printList();
System.out.println( "Second List is" );
llist2.printList();
System.out.println( "Intersection List is" );
intersecn.printList();
System.out.println( "Union List is" );
unin.printList();
}
} /* This code is contributed by Rajat Mishra */
输出如下:
First list is
10 15 4 20
Second list is
8 4 2 10
Intersection list is
4 10
Union list is
2 8 20 4 15 10
复杂度分析:
- 时间复杂度:O(米* n)。
" m"和" n"分别是第一列表和第二列表中存在的元素数。
对于工会:对于list-2中的每个元素, 我们检查该元素是否已经存在于使用list-1生成的结果列表中。
对于交叉点:对于列表1中的每个元素, 我们检查该元素是否也存在于列表2中。 - 辅助空间:O(1)。
不使用任何数据结构来存储值。
方法2(使用合并排序)
在这种方法中, 联合和相交的算法非常相似。首先, 我们对给定的列表进行排序, 然后遍历排序后的列表以获得并集和交集。
以下是获取联合和相交列表的步骤。
- 使用合并排序对第一个链表进行排序。此步骤需要O(mLogm)时间。参考这个帖子有关此步骤的详细信息。
- 使用合并排序对第二个链表进行排序。此步骤需要O(nLogn)时间。参考这个帖子有关此步骤的详细信息。
- 线性扫描两个排序列表以获取并集和交集。此步骤需要O(m + n)时间。可以使用与讨论的排序数组算法相同的算法来执行此步骤这里.
此方法的时间复杂度为O(mLogm + nLogn), 优于方法1的时间复杂度。
方法3(使用散列)
联合(list1, list2)
将结果列表初始化为NULL并创建一个空的哈希表。遍历这两个元素都一个一个地列出, 对于每个要访问的元素, 在哈希表中查找该元素。如果不存在该元素, 则将该元素插入结果列表。如果存在该元素, 则将其忽略。
交叉点(列表1, 列表2)
将结果列表初始化为NULL并创建一个空的哈希表。遍历列表1。对于list1中要访问的每个元素, 请将其插入哈希表。遍历list2, 对于list2中要访问的每个元素, 在哈希表中查找该元素。如果存在该元素, 则将该元素插入结果列表。如果该元素不存在, 则将其忽略。
以上两种方法均假定没有重复项。
// Java code for Union and Intersection of two
// Linked Lists
import java.util.HashMap;
import java.util.HashSet;
class LinkedList {
Node head; // head of list
/* Linked list Node*/
class Node {
int data;
Node next;
Node( int d)
{
data = d;
next = null ;
}
}
/* Utility function to print list */
void printList()
{
Node temp = head;
while (temp != null ) {
System.out.print(temp.data + " " );
temp = temp.next;
}
System.out.println();
}
/* Inserts a node at start of linked list */
void push( int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.next = head;
/* 4. Move the head to point to new Node */
head = new_node;
}
public void append( int new_data)
{
if ( this .head == null ) {
Node n = new Node(new_data);
this .head = n;
return ;
}
Node n1 = this .head;
Node n2 = new Node(new_data);
while (n1.next != null ) {
n1 = n1.next;
}
n1.next = n2;
n2.next = null ;
}
/* A utilty function that returns true if data is
present in linked list else return false */
boolean isPresent(Node head, int data)
{
Node t = head;
while (t != null ) {
if (t.data == data)
return true ;
t = t.next;
}
return false ;
}
LinkedList getIntersection(Node head1, Node head2)
{
HashSet<Integer> hset = new HashSet<>();
Node n1 = head1;
Node n2 = head2;
LinkedList result = new LinkedList();
// loop stores all the elements of list1 in hset
while (n1 != null ) {
if (hset.contains(n1.data)) {
hset.add(n1.data);
}
else {
hset.add(n1.data);
}
n1 = n1.next;
}
// For every element of list2 present in hset
// loop inserts the element into the result
while (n2 != null ) {
if (hset.contains(n2.data)) {
result.push(n2.data);
}
n2 = n2.next;
}
return result;
}
LinkedList getUnion(Node head1, Node head2)
{
// HashMap that will store the
// elements of the lists with their counts
HashMap<Integer, Integer> hmap = new HashMap<>();
Node n1 = head1;
Node n2 = head2;
LinkedList result = new LinkedList();
// loop inserts the elements and the count of
// that element of list1 into the hmap
while (n1 != null ) {
if (hmap.containsKey(n1.data)) {
int val = hmap.get(n1.data);
hmap.put(n1.data, val + 1 );
}
else {
hmap.put(n1.data, 1 );
}
n1 = n1.next;
}
// loop further adds the elements of list2 with
// their counts into the hmap
while (n2 != null ) {
if (hmap.containsKey(n2.data)) {
int val = hmap.get(n2.data);
hmap.put(n2.data, val + 1 );
}
else {
hmap.put(n2.data, 1 );
}
n2 = n2.next;
}
// Eventually add all the elements
// into the result that are present in the hmap
for ( int a : hmap.keySet()) {
result.append(a);
}
return result;
}
/* Driver program to test above functions */
public static void main(String args[])
{
LinkedList llist1 = new LinkedList();
LinkedList llist2 = new LinkedList();
LinkedList union = new LinkedList();
LinkedList intersection = new LinkedList();
/*create a linked list 10->15->4->20 */
llist1.push( 20 );
llist1.push( 4 );
llist1.push( 15 );
llist1.push( 10 );
/*create a linked list 8->4->2->10 */
llist2.push( 10 );
llist2.push( 2 );
llist2.push( 4 );
llist2.push( 8 );
intersection
= intersection.getIntersection(llist1.head, llist2.head);
union = union.getUnion(llist1.head, llist2.head);
System.out.println( "First List is" );
llist1.printList();
System.out.println( "Second List is" );
llist2.printList();
System.out.println( "Intersection List is" );
intersection.printList();
System.out.println( "Union List is" );
union.printList();
}
}
// This code is contributed by Kamal Rawal
输出如下:
First List is
10 15 4 20
Second List is
8 4 2 10
Intersection List is
10 4
Union List is
2 4 20 8 10 15
复杂度分析:
- 时间复杂度:O(m + n)。
" m"和" n"分别是第一列表和第二列表中存在的元素数。
对于工会:遍历两个列表, 将元素存储在哈希图中并更新相应的计数。
对于交叉点:首先遍历list-1, 将其元素存储在Hash-map中, 然后对于list-2中的每个元素, 检查其是否已存在于地图中。这需要O(1)时间。 - 辅助空间:O(m + n)。
使用哈希图数据结构存储值。
如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。