首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试用线性时间排序字符串?

尝试用线性时间排序字符串?
EN

Stack Overflow用户
提问于 2020-03-19 21:55:43
回答 3查看 338关注 0票数 0

我试着用线性时间按字母顺序排列字符串,并考虑使用Pre,我的问题是,在尝试上运行一个预先顺序的横截的时间复杂性是多少?是O(n)吗?

EN

回答 3

Stack Overflow用户

发布于 2020-03-20 13:43:18

在这种情况下,您必须对度量复杂性的方法稍微小心一点。很多时候,人们假装用基于比较的排序来排序N字符串需要O(N log N)时间,但在最坏的情况下并非如此,除非字符串的长度是有界的。但是,如果字符串是随机的,那么这是预期的时间,因此对于许多用例来说,这并不是一个很好的近似。

如果您想使用长的公共前缀来解释可能的长字符串,那么您可以更改N的含义,以引用输入的总大小,包括所有的字符串。使用这个新定义,您可以在O(N) time中对字符串列表进行排序。

将字符串插入trie或更好的基树(https://en.wikipedia.org/wiki/Radix_tree),然后执行预顺序遍历是一种方法,是在O(N)时间中工作的,其中N是输入的总大小。

但是做基数排序更快更容易:https://en.wikipedia.org/wiki/Radix_sort --最重要的数字优先变量--在可变长度输入下工作得最好。

票数 1
EN

Stack Overflow用户

发布于 2020-03-20 13:15:03

在这种情况下,可以应用基数排序在O(n)中对它们进行排序,请参考在c++中实现的以下代码:

代码语言:javascript
复制
#include<iostream>

using namespace std;

class RadixSort {
    public:

        static char charAt(string s,int n){
            return s[n];
        }

        static void countingSort(string arr[],int n,int index,char lower,char upper){
            int countArray[(upper-lower)+2];
            string tempArray[n];

            for(int i =0; i < sizeof(countArray)/sizeof(countArray[0]); i++)
                countArray[i]=0;

            //increase count for char at index
            for(int i=0;i<n;i++){
                int charIndex = (arr[i].length()-1 < index) ? 0 : (charAt(arr[i],index) - lower+1);
                countArray[charIndex]++;
            }

            //sum up countArray;countArray will hold last index for the char at each strings index
            for(int i=1;i<sizeof(countArray)/sizeof(countArray[0]);i++){
                countArray[i] += countArray[i-1];
            }

            for(int i=n-1;i>=0;i--){
                int charIndex = (arr[i].length()-1 < index) ? 0 : (charAt(arr[i],index) - lower+1);
                tempArray[countArray[charIndex]-1] = arr[i];
                countArray[charIndex]--;
            }

            for(int i=0;i<sizeof(tempArray)/sizeof(tempArray[0]);i++){
                arr[i] = tempArray[i];   
            }
        }

        static void radixSort(string arr[],int n,char lower,char upper){
            int maxIndex = 0;
            for(int i=0;i<n;i++){
                if(arr[i].length()-1 > maxIndex){
                maxIndex = arr[i].length()-1;
                }
            }

            for(int i=maxIndex;i>=0;i--){
                countingSort(arr,n,i,lower,upper);
            }
        }
};


int main(){

    string arr[] = {"a", "aa", "aaa","kinga", "bishoy","computer","az"};
    int n = sizeof(arr)/sizeof(arr[0]);
    RadixSort::radixSort(arr,n,'a','z');
    for(int i=0;i<n;i++){
        cout<<arr[i]<<" ";
    }

    return 0;
}
票数 0
EN

Stack Overflow用户

发布于 2020-03-20 13:26:02

不是的。这不是O(n)。它是Omega(k(log(k))n)。没有任何其他限制,正如我从您的问题中了解到的那样,这只是基于比较的排序算法。对长度为k的数组进行排序是在Omega(klog(k))中进行的,并且在没有任何时间连接的情况下进行n次排序将导致Omega(klog(k)n)。您可以在这里阅读更多内容:https://www.geeksforgeeks.org/lower-bound-on-comparison-based-sorting-algorithms/

如果你认为k是有界的,因为没有英语的单词超过10^1000000 (这可能比地球上的原子还要大),那么排序一个有界长度的数组在O(1)中,在n个时间内进行排序将导致O(n)。

你从处理无穷大中得到了很多,但有时你必须偿还.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60765628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档