给定两个链表,创建并集和交集列表,其中包含给定列表中存在的元素的并集和交集。输出列表中元素的顺序无关紧要。
例子:
Input:
List1: 10 -> 15 -> 4 -> 20
List2: 8 -> 4 -> 2 -> 10
Output:
Intersection List: 4 -> 10
Union List: 2 -> 8 -> 20 -> 4 -> 15 -> 10
Explanation: In this two lists 4 and 10 nodes
are common. The union lists contains
all the nodes of both the lists.
Input:
List1: 1 -> 2 -> 3 -> 4
List2: 3 -> 4 -> 8 -> 10
Output:
Intersection List: 3 -> 4
Union List: 1 -> 2 -> 3 -> 4 -> 8 -> 10
Explanation: In this two lists 4 and 3 nodes
are common. The union lists contains
all the nodes of both the lists.
我们已经讨论过这个问题的方法一和方法二。
在这篇文章中,它的方法 3(使用散列)以 O(m+n) 的时间复杂度进行讨论,即优于前面讨论的两种方法。
Implementation:
1- Start traversing both the lists.
a) Store the current element of both lists
with its occurrence in the map.
2- For Union: Store all the elements of the map
in the resultant list.
3- For Intersection: Store all the elements only
with an occurrence of 2 as 2 denotes that
they are present in both the lists.
下面是上述步骤的 C++ 实现。
// C++ program to find union and intersection of
// two unsorted linked lists in O(m+n) time.
#include
using namespace std;
/* Link list node */
struct Node {
int data;
struct Node* next;
};
/* 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;
}
/* Utility function to store the
elements of both list */
void storeEle(struct Node* head1, struct Node* head2,
unordered_map& eleOcc)
{
struct Node* ptr1 = head1;
struct Node* ptr2 = head2;
// Traverse both lists
while (ptr1 != NULL || ptr2 != NULL) {
// store element in the map
if (ptr1 != NULL) {
eleOcc[ptr1->data]++;
ptr1 = ptr1->next;
}
// store element in the map
if (ptr2 != NULL) {
eleOcc[ptr2->data]++;
ptr2 = ptr2->next;
}
}
}
/* Function to get the union of two
linked lists head1 and head2 */
struct Node* getUnion(
unordered_map eleOcc)
{
struct Node* result = NULL;
// Push all the elements into
// the resultant list
for (auto it = eleOcc.begin(); it != eleOcc.end(); it++)
push(&result, it->first);
return result;
}
/* Function to get the intersection of
two linked lists head1 and head2 */
struct Node* getIntersection(
unordered_map eleOcc)
{
struct Node* result = NULL;
// Push a node with an element
// having occurrence of 2 as that
// means the current element is
// present in both the lists
for (auto it = eleOcc.begin();
it != eleOcc.end(); it++)
if (it->second == 2)
push(&result, it->first);
// return resultant list
return result;
}
/* A utility function to print a linked list*/
void printList(struct Node* node)
{
while (node != NULL) {
printf("%d ", node->data);
node = node->next;
}
}
// Prints union and intersection of
// lists with head1 and head2.
void printUnionIntersection(Node* head1,
Node* head2)
{
// Store all the elements of
// both lists in the map
unordered_map eleOcc;
storeEle(head1, head2, eleOcc);
Node* intersection_list = getIntersection(eleOcc);
Node* union_list = getUnion(eleOcc);
printf("\nIntersection list is \n");
printList(intersection_list);
printf("\nUnion list is \n");
printList(union_list);
}
/* Driver program to test above function*/
int main()
{
/* Start with the empty list */
struct Node* head1 = NULL;
struct Node* head2 = NULL;
/* create a linked list 11->10->15->4->20 */
push(&head1, 1);
push(&head1, 2);
push(&head1, 3);
push(&head1, 4);
push(&head1, 5);
/* create a linked list 8->4->2->10 */
push(&head2, 1);
push(&head2, 3);
push(&head2, 5);
push(&head2, 6);
printf("First list is \n");
printList(head1);
printf("\nSecond list is \n");
printList(head2);
printUnionIntersection(head1, head2);
return 0;
}
输出:
First list is
5 4 3 2 1
Second list is
6 5 3 1
Intersection list is
3 5 1
Union list is
3 4 6 5 2 1
我们还可以通过为两个列表维护单独的 Hash 来处理重复的情况。
复杂度分析:
- 时间复杂度: O(m+n)。
这里 ‘m’ 和 ‘n’ 分别是第一个和第二个列表中存在的元素数。
原因:
对于 Union:遍历两个列表,将元素存储在 Hash-map 中并更新各自的计数。
对于交集:检查哈希映射中元素的计数是否为“2”。 - 辅助空间: O(m+n)。
使用 Hash-map 数据结构来存储值。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。