给定两个已排序的单向链表,合并这两个链表。
例子: list1: 1 2 3 5 7 list2: 0 4 6 7 10 ---> 0 1 2 3 4 5 6 7 7 10
尽管解决方案非常简单,并且有多种不同的实现方法,包括使用或不使用递归(请参见此处http://www.geeksforgeeks.org/merge-two-sorted-linked-lists/,查看Method 3),但是,
我在想这种实现的O复杂度会是多少:
如果其中一个列表为空,则返回另一个列表; 否则,使用sortedInsert函数将第二个列表的每个节点插入到第一个列表中。该函数基本上会扫描列表直到找到正确的位置。由于两个列表都已经排序,因此无需每次将节点与第一个列表中的所有节点进行比较,可以从最后添加的节点开始比较。
例如:继续前面的示例,如果已添加了4,则下一次比较可以安全地从4开始: list1: 0 1 2 3 4 5 7 list2: 6 7 10 现在将6与4进行比较,而不是与1 2 3 4...进行比较。
如果我将一个元素与第一个列表中的所有元素进行比较,则复杂度为O(m * n),其中m = #list2,n = #list1,但是考虑到这种“优化”,复杂度会是多少?
实施方案:
例子: list1: 1 2 3 5 7 list2: 0 4 6 7 10 ---> 0 1 2 3 4 5 6 7 7 10
尽管解决方案非常简单,并且有多种不同的实现方法,包括使用或不使用递归(请参见此处http://www.geeksforgeeks.org/merge-two-sorted-linked-lists/,查看Method 3),但是,
我在想这种实现的O复杂度会是多少:
如果其中一个列表为空,则返回另一个列表; 否则,使用sortedInsert函数将第二个列表的每个节点插入到第一个列表中。该函数基本上会扫描列表直到找到正确的位置。由于两个列表都已经排序,因此无需每次将节点与第一个列表中的所有节点进行比较,可以从最后添加的节点开始比较。
例如:继续前面的示例,如果已添加了4,则下一次比较可以安全地从4开始: list1: 0 1 2 3 4 5 7 list2: 6 7 10 现在将6与4进行比较,而不是与1 2 3 4...进行比较。
如果我将一个元素与第一个列表中的所有元素进行比较,则复杂度为O(m * n),其中m = #list2,n = #list1,但是考虑到这种“优化”,复杂度会是多少?
实施方案:
// Insert a new node in a sorted list
int sortedInsert(struct ListNode **head, struct ListNode* newNode) {
int headUpdated = 0;
struct ListNode *current;
// The list is empty or the new element has to be added as first element
if (*head == NULL || (*head)->data >= newNode->data) {
newNode->next = *head;
*head = newNode;
headUpdated = 1;
}
else {
// Locate the node before the point of insertion
current = *head;
while (current->next != NULL && current->next->data < newNode->data)
current = current->next;
newNode->next = current->next;
current->next = newNode;
}
return headUpdated;
}
struct ListNode *mergeLists(struct ListNode *head1, struct ListNode *head2) {
if (head1 == NULL)
return head2;
if (head2 == NULL)
return head1;
// Store the node in the first list where to start the comparisons
struct ListNode *first = head1;
while (head2) {
struct ListNode *head2Next = head2->next;
printf("Adding %d starting comparison from %d\n", head2->data, first->data);
if (sortedInsert(&first, head2))
head1 = first;
first = head2;
head2 = head2Next;
}
return head1;
}
current = current->next
。总共有n
次插入操作,最多会有m + n - 1
次节点遍历操作。 - Daniel Fischer