了解从链表中删除重复项的复杂性
Posted
技术标签:
【中文标题】了解从链表中删除重复项的复杂性【英文标题】:Understanding complexity of deleting duplicates from a linked-list 【发布时间】:2017-05-25 17:23:10 【问题描述】:我编写了这个程序来从一个未排序的链表中删除重复的节点:
#include<bits/stdc++.h>
using namespace std;
/* A linked list node */
struct Node
int data;
struct Node *next;
;
// Utility function to create a new Node
struct Node *newNode(int data)
Node *temp = new Node;
temp->data = data;
temp->next = NULL;
return temp;
/* Function to remove duplicates from a
unsorted linked list */
void removeDuplicates(struct Node *start)
// Hash to store seen values
unordered_set<int> seen;
/* Pick elements one by one */
struct Node *curr = start;
struct Node *prev = NULL;
while (curr != NULL)
// If current value is seen before
if (seen.find(curr->data) != seen.end())
prev->next = curr->next;
delete (curr);
else
seen.insert(curr->data);
prev = curr;
curr = prev->next;
/* Function to print nodes in a given linked list */
void printList(struct Node *node)
while (node != NULL)
printf("%d ", node->data);
node = node->next;
/* Driver program to test above function */
int main()
/* The constructed linked list is:
10->12->11->11->12->11->10*/
struct Node *start = newNode(10);
start->next = newNode(12);
start->next->next = newNode(11);
start->next->next->next = newNode(11);
start->next->next->next->next = newNode(12);
start->next->next->next->next->next =
newNode(11);
start->next->next->next->next->next->next =
newNode(10);
printf("Linked list before removing duplicates : \n");
printList(start);
removeDuplicates(start);
printf("\nLinked list after removing duplicates : \n");
printList(start);
return 0;
在哈希表中查找每个元素会影响复杂性吗?如果是,考虑到该集合是作为二叉搜索树实现的,其中在最坏情况下搜索元素的成本为 O(logn),该算法的时间复杂度应该是多少。 据我说 T(n)=T(n-1)+log(n-1) 即。第 n 个元素将执行 log(n-1) 比较(即具有 n-1 个元素的树的高度) 请给出数学分析。
【问题讨论】:
这取决于你的哈希表是否有很多冲突,通常很少,所以它可能是 O(1),因此不会影响复杂性。 嗯,unordered_set 实际上具有恒定的时间复杂度(平均而言),因此为 O(1)。 您共享的方法尽可能高效,因为您需要遍历列表至少一次 O(N),删除重复项,使用集合或无序集合不会影响整体时间因为这两个将分别是 O(log(N)) 和 O(1) 用于查找。 @AmitKumar 在最坏的情况下,对于 N 个元素,查找的总成本将变为 N*O(logN) 。这肯定会影响复杂性。 【参考方案1】:在哈希表中查找每个元素会影响复杂度吗?
好吧,在您的代码中,您使用的是 unordered_set,它的平均复杂度为 O(1),所以简单的答案是 - 否。
...考虑到该集合被实现为二叉搜索树,其中搜索元素的成本在最坏情况下为 O(logn)。
同样,您选择了unordered_set
,它不是二分搜索。我相信set
的一些实现使用红/黑树,你会看到 O(logN),但对于unordered_set
,它应该是恒定的时间。所以现在唯一的问题是你的链表的遍历。其中,由于您在访问每个节点时只是沿一个方向行走,因此是 O(N) 操作。
【讨论】:
如果我使用 set 而不是 unordered_set 会怎样。这将如何影响复杂性? @abhishekgupta - 我已经回答过了。使用std::set
,您正在查看 O(logN) 而不是 O(1) 摊销。您仍然需要遍历 O(N) 的列表,并且设置的查找为 O(logN)。以上是关于了解从链表中删除重复项的复杂性的主要内容,如果未能解决你的问题,请参考以下文章