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?