我编写了以下函数,该函数在创建排序的字符串序列时计算字符串的重复实例。然而它很慢,然后我意识到这是O(n ^ 2)。所以我想把它做成O(n logn),但我不知道如何继续。有没有已知的方法将这种n ^ 2算法转换为nlogn?如何转换呢?
void insert (struct listNode **ptr, char *value) {
struct listNode *newPtr;
int cmp;
// find a place to instert node to LL
while(*ptr){
// Comparision to detect & remove duplicates nodes
cmp = strcmp(value, (*ptr)->data);
// duplicate
if(cmp == 0){
(*ptr)->occurrence++;
return;
}
// the point where i need to add the node
if(cmp < 0)
break;
ptr = &(*ptr)->next;
}
// now here *ptr points to the pointer that i want to change
// it can be NULL, if we are at the end of the LL
newPtr = malloc(sizeof *newPtr);
if(!newPtr)
return;
newPtr->data = strdup(value);
newPtr->occurrence = 1;
if(newPtr->data == NULL){
free(newPtr);
return;
}
// here we are connecting our brand new node to the LL
newPtr->next = *ptr;
*ptr = newPtr;
}
struct listNode {
char *data;
struct listNode *next;
int occurrence;
};
答案 0 :(得分:3)
是否有任何已知方法可将此类
n
2 算法转换为n
* logn
?
如果您繁殖的两个n
中的一个来自访问线性数据结构(例如您的链接列表),则可以改进为n
* log n
转向更快的数据结构,例如平衡的二叉树。
这将转换为使用二叉树中的搜索替换while
循环搜索(线性),该搜索是日志n
。
答案 1 :(得分:0)
插入排序是一种单独的排序技术。如果你convert(according complexity)
这个,它将是另一种排序技术。
我认为link
Sorting Algorithm对find different type complexity of sorting technique
有帮助。
答案 2 :(得分:0)
插入排序具有最坏情况时间O(N2)。我建议使用另一种具有Theta(n lg n)时间复杂度的算法,例如合并排序,而不是试图改变 stable 算法的时间复杂度。
让我们得到一些有用的信息,这些信息可能会帮助人们了解如何将此类问题的时间复杂性降低到Theta(n lg n)。
通常,您可以使用分而治之技术来减少排序问题的时间复杂度到Theta(n lg n)。
让我们一起理解这种算法设计范式。
分而治之
这个想法是,如果你将一个敌人分成小块,每一块,从而可以征服敌人。当应用于计算机问题时,分而治之三包括三个步骤。
使用分而治之进行排序
事实证明这是非常容易的,它可能是令人惊讶的,它是渐近最优的。关键的观察是合并两个排序列表的速度很快(时间与列表大小呈线性关系)。步骤是
合并排序的运行时间T(n)
合并:合并n个元素需要Theta(n) 总计:
如果n = 1,则T(n)= Theta(1) 如果n> 1,则T(n)= 2T(n / 2)+ Theta(n)。 1
=&GT; T(n)= Theta(n lg n)
有关更多信息和示例,请查看此link。
答案 3 :(得分:0)
通常,您不会通过重新编写现有算法来提高其复杂性,而是从一开始就将其设计为高效。无论如何,让我们玩这个游戏。
算法的工作原理是保持N
第一个元素的列表,按排序顺序排列,并逐个合并其余元素。这种方法的成本很高,包括对排序列表O(N)
进行线性搜索,总计O(N²)
进行排序。
众所周知,通过二分查找,可以在O(Log(N))
的时间内更有效地搜索排序列表。不幸的是,这适用于数组(用于随机访问),但是数组需要O(N)
次插入。这种困境的解决方案很久以前就被发现是(平衡的)二叉树数据结构,它允许快速搜索和快速插入。
另一种不太明显的方法是尝试减少插入次数。实际上,如果您一次插入多个元素,并按排序顺序排列这些元素,则可以在一次传递中完成插入:这称为合并操作。
正如@ChakerMallek详细说明的那样,如果将列表拆分为两半,则将它们分开排序,全局排序相当于合并,并按时完成O(N)
。两个子列表的排序可以递归地完成,导致众所周知的MergeSort,非常适合于链表表示并且最佳地有效。它甚至可以适应在近乎排序的列表上更快。
答案 4 :(得分:0)
如果我正确阅读,您使用的是插入排序,其复杂度为O(n ^ 2)。但是,如果在查找阶段(while循环)切换到二进制搜索,则可以在O(nlogn)中执行此操作。