C 时间复杂性?
问题是找到两个排序链表的交集,并将公共元素存储在第三个列表中 我的方法是创建临时指针C 时间复杂性?,c,linked-list,time-complexity,singly-linked-list,C,Linked List,Time Complexity,Singly Linked List,问题是找到两个排序链表的交集,并将公共元素存储在第三个列表中 我的方法是创建临时指针temp1和temp2分别初始化head1(列表1的头)和head2(列表2的头)。然后遍历这两个列表并比较元素,并相应地移动temp1和temp2。代码运行良好 测试用例: 第一个链表=>1->2->3->4->6 第二个链表是2->4->6->8,然后函数应该创建并返回第三个链表2->4->6 但我对时间复杂性感到困惑:O(m+n)或O(min(m,n))?(m,n是列表1和列表2中的元素数) 我的代码: #
temp1
和temp2
分别初始化head1
(列表1的头)和head2
(列表2的头)。然后遍历这两个列表并比较元素,并相应地移动temp1
和temp2
。代码运行良好
测试用例:
第一个链表=>1->2->3->4->6
第二个链表是2->4->6->8,然后函数应该创建并返回第三个链表2->4->6
但我对时间复杂性感到困惑:O(m+n)或O(min(m,n))?(m,n是列表1和列表2中的元素数)
我的代码:
#include<stdio.h>
#include<stdlib.h>
/* Link list node */
struct Node
{
int data;
struct Node* next;
};
void append(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
struct Node *last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be the last node, so make next
of it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty, then make the new node as head */
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
return;
}
struct Node* sortedIntersect(struct Node* head1,struct Node*head2)
{
struct Node*head3=NULL;
struct Node*temp1=head1;
struct Node*temp2=head2;
while(temp1!=NULL&&temp2!=NULL)
{
if(temp1->data<temp2->data)
{if(temp1->next!=NULL)
temp1=temp1->next;
else
break;
}
else if(temp1->data>temp2->data)
{
if(temp2->next!=NULL)
temp2=temp2->next;
else{
break;
}
}
else
{
append(&head3,temp1->data);
temp1=temp1->next;
temp2=temp2->next;
}
}
return head3;
}
/* Function to insert a node at the beginging of the 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;
}
/* Function to print nodes in a given linked list */
void printList(struct Node *node)
{
while (node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
int main()
{
/* Start with the empty lists */
struct Node* a = NULL;
struct Node* b = NULL;
struct Node *intersect = NULL;
/* Let us create the first sorted linked list to test the functions
Created linked list will be 1->2->3->4->5->6 */
push(&a, 6);
push(&a, 5);
push(&a, 4);
push(&a, 3);
push(&a, 2);
push(&a, 1);
/* Let us create the second sorted linked list
Created linked list will be 2->4->6->8 */
push(&b, 8);
push(&b, 6);
push(&b, 4);
push(&b, 2);
/* Find the intersection two linked lists */
intersect = sortedIntersect(a, b);
printf("\n Linked list containing common items of a & b \n ");
printList(intersect);
return 0;
}
#包括
#包括
/*链接列表节点*/
结构体类型
{
int数据;
结构节点*下一步;
};
void append(结构节点**head\u ref,int new\u数据)
{
/*1.分配节点*/
结构节点*新节点=(结构节点*)malloc(sizeof(结构节点));
结构节点*last=*head_ref;/*在步骤5中使用*/
/*2.输入数据*/
新建_节点->数据=新建_数据;
/*3.这个新节点将是最后一个节点,因此请创建下一个节点
它的值为空*/
新建节点->下一步=空;
/*4.如果链表为空,则将新节点设为head*/
如果(*head_ref==NULL)
{
*head\u ref=新节点;
返回;
}
/*5.否则遍历到最后一个节点*/
while(上一次->下一次!=NULL)
最后一个=最后一个->下一个;
/*6.更改最后一个节点的下一个节点*/
last->next=新建_节点;
返回;
}
结构节点*分拣机门派(结构节点*头1、结构节点*head2)
{
结构节点*head3=NULL;
结构节点*temp1=head1;
结构节点*temp2=head2;
while(temp1!=NULL&&temp2!=NULL)
{
if(temp1->datadata)
{if(temp1->next!=NULL)
temp1=temp1->next;
其他的
打破
}
else if(temp1->data>temp2->data)
{
如果(temp2->next!=NULL)
temp2=temp2->next;
否则{
打破
}
}
其他的
{
追加(&head3,temp1->data);
temp1=temp1->next;
temp2=temp2->next;
}
}
返回头3;
}
/*函数在链表的开头插入一个节点*/
无效推送(结构节点**head\u ref,int new\u数据)
{
/*分配节点*/
结构节点*新节点=(结构节点*)malloc(sizeof(结构节点));
/*输入数据*/
新建_节点->数据=新建_数据;
/*将旧列表链接到新节点*/
新建节点->下一步=(*head\u ref);
/*移动头部以指向新节点*/
(*head_ref)=新节点;
}
/*函数打印给定链表中的节点*/
无效打印列表(结构节点*节点)
{
while(节点!=NULL)
{
printf(“%d”,节点->数据);
节点=节点->下一步;
}
}
int main()
{
/*从空列表开始*/
结构节点*a=NULL;
结构节点*b=NULL;
结构节点*intersect=NULL;
/*让我们创建第一个排序的链表来测试函数
创建的链表将是1->2->3->4->5->6*/
推(a,6);
推(a,5);
推(a,4);
推(a,3);
推(a,2);
推送(&a,1);
/*让我们创建第二个排序链表
创建的链表将是2->4->6->8*/
推送(和b,8);
推送(b,6);
推送(&b,4);
推送(&b,2);
/*找到两个链表的交点*/
intersect=sortedIntersect(a,b);
printf(“\n包含a&b常用项的链接列表\n”);
打印列表(intersect);
返回0;
}
正如在的每次迭代中,至少有一个指针转到下一个,并且终止的条件是没有一个指针到达终点,时间复杂度将是O(min(m,n))
这是一个可以在O(m+n)
中解决的问题
然而,这个解决方案不是O(m+n)
。在方法intersectSorted
中添加的每个元素都与方法append
一起添加,该方法遍历整个当前输出列表
因此,时间复杂度是O((m+n)log(min(m,n))
在最坏情况下O(m+n)
示例:{1,3,5,7}{2,4,6,8}
在本例中,您将遍历
名单
在平均值的情况下
O(min(m,n) + number of times you don't increment the smaller list)
示例:{1,2,3,4,6}{2,4,6,8,9,10}
在这种情况下,您终止
当您到达第一行列表的末尾但在您之间时,循环
增加第二个列表而不增加第一个列表
在最佳情况下
为O(min(m,n))
示例:{1,2,3}{1,2,3,4,}
在这种情况下,您将终止
到达第一个列表末尾后的循环
请你解释一下你是如何做到这一点的?我不是100%确定如何推导它,但重复遍历一个不断增大的列表通常是O(n logn),但这种最坏的情况永远不会发生,对吗?(对于时间复杂度O(m+n+log(m+n))是正确的)如果两个列表中都有最大的公共元素,那么这将是链表遍历的最坏情况,另一方面,如果没有公共元素,那么while循环将是最坏情况,因此实际的最坏情况可以在更严格的范围内。但我们仍然可以说,所花费的时间将始终小于此值。@jane,这可能是t是的,但我想说最坏的情况至少是O(m logm)或类似的东西。追加操作会破坏任何线性。是的,这是真的。但是你能检查一下你的时间复杂度吗,它应该是O(m+n+(m+n)log(m+n)),正如你之前所说的,或者log项前面的因子不依赖于m或n?