You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按频率排序字符串数组:现有O(nlogn)解法,是否存在更优方案?

Optimizing String Sort by Frequency and Lexicographical Order

Great question! Let’s break down whether we can do better than your current HashMap + sorting approach, and when it makes sense to bother.

First off, your existing solution—using a HashMap to count frequencies, then sorting the entries by frequency (descending) and lexicographical order (ascending) when frequencies tie—is totally solid. Its O(n log n) time complexity is efficient enough for most real-world use cases, since sorting algorithms are highly optimized and the constant factors are usually negligible.

But if you’re dealing with very large input sizes (think millions of strings) or datasets with tons of duplicate values, we can shave off some time using a bucket sort approach, which brings the time complexity down to O(n + k log k) (where k is the number of unique strings, k ≤ n). Here’s how it works:

Step-by-Step Breakdown

  1. Count Frequencies (Same as Before)
    Use a HashMap to tally up how many times each string appears. This is still O(n) time—no way around this, since we have to scan every input string once.
  2. Group Strings by Frequency
    Create an array of "buckets" where the index represents the frequency count, and each bucket holds all strings that appear exactly that many times. For example, the bucket at index 2 will contain every string that shows up twice. This step runs in O(k) time, since we’re just iterating over the unique strings.
  3. Sort Buckets & Build Result
    • Since we need lexicographical order when frequencies are equal, we first sort each bucket’s strings in ascending a-z order. The total time for this is O(k log k) (summing the sort time for each bucket).
    • Then, iterate from the highest-frequency bucket down to the lowest. For each string in the bucket, add it to the result list exactly as many times as its frequency. This final step is O(n) time, since we’re just outputting all n input strings.

Why This Is Better (Sometimes)

When k (unique strings) is much smaller than n (total strings), the O(k log k) sorting step is way cheaper than sorting all n elements directly. For example, if your input is mostly duplicates of a handful of strings, this approach will feel almost O(n) fast.

Example Implementation (Java)

import java.util.*;

public class FrequencySorter {
    public List<String> sortByFrequency(String[] strs) {
        // Step 1: Count frequencies
        Map<String, Integer> freqMap = new HashMap<>();
        for (String s : strs) {
            freqMap.put(s, freqMap.getOrDefault(s, 0) + 1);
        }

        // Step 2: Initialize frequency buckets
        List<String>[] buckets = new List[strs.length + 1];
        for (int i = 0; i < buckets.length; i++) {
            buckets[i] = new ArrayList<>();
        }
        for (Map.Entry<String, Integer> entry : freqMap.entrySet()) {
            buckets[entry.getValue()].add(entry.getKey());
        }

        // Step 3: Sort buckets and build result
        List<String> result = new ArrayList<>();
        for (int i = buckets.length - 1; i >= 0; i--) {
            // Sort bucket lexicographically
            Collections.sort(buckets[i]);
            // Add each string i times to the result
            for (String s : buckets[i]) {
                for (int j = 0; j < i; j++) {
                    result.add(s);
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        FrequencySorter sorter = new FrequencySorter();
        String[] input = {"foo","cat","foo","cool","cat","goo","cool"};
        System.out.println(sorter.sortByFrequency(input));
        // Output: [cat, cat, cool, cool, foo, foo, goo]
    }
}

Quick Notes on Edge Cases & Tweaks

  • TreeMap vs HashMap: Don’t use a TreeMap to count frequencies—it’ll sort keys automatically but add O(n log k) overhead to the counting step, which is worse than using a HashMap first then sorting buckets.
  • Fixed-Range Strings: If your input strings are limited (e.g., all lowercase letters, fixed length), you could use an array instead of a HashMap for frequency counting to squeeze out a tiny bit more speed, but this is a niche optimization.

Final Takeaway

  • Stick with your original O(n log n) approach for most cases—it’s simple, easy to maintain, and fast enough.
  • Switch to bucket sort only when you’re dealing with extremely large datasets or high duplication rates, where the performance gain justifies the extra code complexity.

内容的提问来源于stack exchange,提问作者kevinjoeiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:44:09