アルゴリズム-文字の出現頻度に従ってソート

アルゴリズム-文字の出現頻度に従ってソート

1.文字の頻度に従って並べ替えます

451.文字の頻度で並べ替える

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:
"tree"

输出:
"eert"

解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
示例 2:

输入:
"cccaaa"

输出:
"cccaaa"

解释:
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
示例 3:

输入:
"Aabb"

输出:
"bbAa"

解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。

この質問は、セルフハッシュの優れたケースです。ハッシュテーブルの性質を使用して、時間の複雑さをO(N)に最適化できます。
主なアイデアは、カウンター配列を作成することです配列インデックスは文字のASCIIコード値であり、配列の内容は表示される文字です。次に、毎回配列内の最大の要素を検索します。検索が完了すると、最大の要素の出現回数は0に設定されます(記憶検索)。文字が0から128の間であるため、検索時間の複雑さは実際にはOです。 (1)したがって、合計時間の複雑さはO(N)です。

   public String frequencySort(String s) {
    
    
        if(s==null){
    
    
            return s;
        }
        int[] counter=new int[128];//自hash,统计字符出现次数
        char[] cs=s.toCharArray();
        for(char c:cs){
    
    
            counter[c]++;
        }

        int curr=0;
        while (curr<cs.length){
    
    
            int[] result=findMax(counter);//寻找出现次数最多的元素,返回元素和元素出现次数,时间复杂度O(128)也就是O(1)
            char c=(char) result[0];//找到的元素
            int count=result[1];//元素出现次数
            while (count-->0){
    
    
                cs[curr++]=c;//填充数据
            }
        }
        return new String(cs);

    }

    public int[] findMax(int[] counter){
    
    
        int count=0;
        int index=0;
        for(int i=0;i<='z';i++){
    
    
            if(counter[i]>count){
    
    
                count=counter[i];
                index=i;
            }
        }
        counter[index]=0;//使用完了,下次不再使用了
        return new int[]{
    
    index,count};
    }

実行速度も非常に速いですが、現在、私以外のリートコードの最速は3msで、アルゴリズムは2msに達しています。

执行用时 :2 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗 :40.3 MB, 在所有 Java 提交中击败了11.11%的用户

実際、このアルゴリズムは最適化できます。2つのポイントが指摘されています
。1。関数呼び出しには呼び出しスタックのオーバーヘッドがあるため、サブ関数を使用する代わりに、毎回最大値が検索される場所をループ本体に配置できます
。2。この方法時間の複雑さはO(N)ですが、実際には改善できます。登場したキャラクターを判断するだけです。

最初のポイントとして、次の最適化を行うことができます

    public String frequencySort(String s) {
    
    
        if(s==null){
    
    
            return s;
        }
        int[] counter=new int[128];//自hash,统计字符出现次数
        char[] cs=s.toCharArray();
        for(char c:cs){
    
    
            counter[c]++;
        }
        int curr=0;
        while (curr<cs.length){
    
    
            int count=0;
            char c=0;
            //下面的for循环,时间复杂度为O(1),因为最坏情况下遍历次数为'z'=122次
            for(int i=0;i<='z';i++){
    
    
                if(counter[i]>count){
    
    
                    count=counter[i];
                    c=(char)i;
                }
            }
            counter[c]=0;//使用完了,下次不再使用了
            while (count-->0){
    
    
                cs[curr++]=c;//填充数据
            }
        }
        return new String(cs);
    }

おすすめ

転載: blog.csdn.net/qq_23594799/article/details/105870955