2026-02-20:众数频率字符。用go语言,给定一个只含小写字母的字符串 s。 把所有在 s 中出现次数相同的字母归为一类:对于某个整数 k,出现恰好 k

0 阅读4分钟

2026-02-20:众数频率字符。用go语言,给定一个只含小写字母的字符串 s。

把所有在 s 中出现次数相同的字母归为一类:对于某个整数 k,出现恰好 k 次的字母构成一组。

我们要找出那一组字母,其成员(不同字母)数量比其它任何组都多。

将该组里的所有字母串成一个返回值字符串,字母顺序不限。

如果存在两个或多个组成员数相同且并列最多,则取出现次数 k 较大的那一组。

1 <= s.length <= 100。

s 只包含小写英文字母。

输入: s = "aaabbbccdddde"。

输出: "ab"。

解释:

频率 (k)组中不同字符组大小是否众数?
4{d}1
3{a, b}2
2{c}1
1{e}1

字符 'a' 和 'b' 的频率相同,都为 3,它们在众数频率组中。

题目来自力扣3692。

解题思路分析

题目要求:根据字符出现的频率对字母进行分组,找出成员数量最多的那一组(如果存在并列最多,则选择频率 k 较大的组),并将该组的所有字母拼接成字符串返回。

以输入 s = "aaabbbccdddde" 为例,详细步骤如下:

第一步:统计每个字母的出现次数

  • 遍历字符串 "aaabbbccdddde",统计每个小写字母出现的次数:
    • a: 3 次
    • b: 3 次
    • c: 2 次
    • d: 4 次
    • e: 1 次

第二步:按频率分组

  • 将出现次数相同的字母归为一组,用哈希表存储,key 为频率 k,value 为该频率下的字母列表:
    • 频率 4: {d}(1 个字母)
    • 频率 3: {a, b}(2 个字母)
    • 频率 2: {c}(1 个字母)
    • 频率 1: {e}(1 个字母)

第三步:找出成员最多的组

  • 比较每组中的字母数量:
    • 频率 4 组:1 个字母
    • 频率 3 组:2 个字母
    • 频率 2 组:1 个字母
    • 频率 1 组:1 个字母
  • 频率 3 组的成员数量最多(2 个),因此它是候选组。

第四步:处理并列情况

  • 假设有两个组的成员数量相同且都是最多,则选择频率 k 较大的组。
  • 本例中没有并列情况,直接选择频率 3 组。

第五步:输出结果

  • 将频率 3 组的字母列表 [a, b] 拼接成字符串 "ab"(字母顺序不限)。

最终输出

ab

复杂度分析

时间复杂度

  • 统计字母频率:遍历一次字符串,长度为 n,时间复杂度 O(n)
  • 分组和找最大组:遍历 26 个字母的计数数组,进行哈希表操作和比较,时间复杂度 O(26) ≈ O(1)
  • 总时间复杂度:O(n) + O(1) = O(n),其中 n 为字符串长度

额外空间复杂度

  • 计数数组:固定大小 26,O(1)
  • 分组哈希表:最多存储 26 个不同频率的组,每个组存储字母列表,总字母数不超过 26,所以空间 O(26) ≈ O(1)
  • 总额外空间复杂度O(1)(常数空间)

Go完整代码如下:

package main

import (
	"fmt"
)

func majorityFrequencyGroup(s string) string {
	cnt := [26]int{}
	for _, b := range s {
		cnt[b-'a']++
	}

	groups := map[int][]byte{}
	mx := 0
	for i, c := range cnt {
		if c == 0 {
			continue
		}
		groups[c] = append(groups[c], 'a'+byte(i))
		if len(groups[c]) > len(groups[mx]) || len(groups[c]) == len(groups[mx]) && c > mx {
			mx = c
		}
	}

	return string(groups[mx])
}

func main() {
	s := "aaabbbccdddde"
	result := majorityFrequencyGroup(s)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

def majority_frequency_group(s: str) -> str:
    # 统计每个字符的出现频率
    cnt = [0] * 26
    for ch in s:
        cnt[ord(ch) - ord('a')] += 1
    
    # 按频率分组存储字符
    groups = {}
    mx = 0  # 记录当前最大频率
    
    for i, c in enumerate(cnt):
        if c == 0:
            continue
        
        # 将字符添加到对应频率的分组中
        if c not in groups:
            groups[c] = []
        groups[c].append(chr(ord('a') + i))
        
        # 更新最大频率的选择标准:
        # 1. 当前分组的字符数量大于最大频率分组的字符数量
        # 2. 或者字符数量相等但当前频率值更大
        if mx not in groups:
            mx = c
        elif len(groups[c]) > len(groups[mx]):
            mx = c
        elif len(groups[c]) == len(groups[mx]) and c > mx:
            mx = c
    
    # 返回最大频率分组中的所有字符组成的字符串
    return ''.join(sorted(groups[mx]))  # 排序以保证输出顺序一致

# 测试
if __name__ == "__main__":
    s = "aaabbbccdddde"
    result = majority_frequency_group(s)
    print(result)

在这里插入图片描述

C++完整代码如下:

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>

using namespace std;

string majorityFrequencyGroup(string s) {
    // 统计每个字符的出现频率
    vector<int> cnt(26, 0);
    for (char ch : s) {
        cnt[ch - 'a']++;
    }

    // 按频率分组存储字符
    unordered_map<int, vector<char>> groups;
    int mx = 0;  // 记录当前最大频率

    for (int i = 0; i < 26; i++) {
        int c = cnt[i];
        if (c == 0) {
            continue;
        }

        // 将字符添加到对应频率的分组中
        groups[c].push_back('a' + i);

        // 更新最大频率的选择标准:
        // 1. 当前分组的字符数量大于最大频率分组的字符数量
        // 2. 或者字符数量相等但当前频率值更大
        if (groups.count(mx) == 0) {
            mx = c;
        } else if (groups[c].size() > groups[mx].size()) {
            mx = c;
        } else if (groups[c].size() == groups[mx].size() && c > mx) {
            mx = c;
        }
    }

    // 对结果中的字符排序,保证输出顺序一致
    vector<char>& result_chars = groups[mx];
    sort(result_chars.begin(), result_chars.end());

    // 将字符向量转换为字符串
    return string(result_chars.begin(), result_chars.end());
}

int main() {
    string s = "aaabbbccdddde";
    string result = majorityFrequencyGroup(s);
    cout << result << endl;
    return 0;
}

在这里插入图片描述