华为OD字符串处理:单词排序与频率统计实战
2026/9/19 7:24:05 网站建设 项目流程

1. 题目解析与需求拆解

今天我们来拆解一道来自华为OD机考的字符串处理题目。这道题看似简单,但实际考察了多种字符串操作和排序逻辑的综合运用能力。作为经历过多次机考的老手,我发现这类题目往往在边界条件和排序规则上设置陷阱,需要格外小心。

题目要求我们对给定字符串进行两步处理:

  1. 对每个单词内部字符按字典序重新排列
  2. 对所有单词按特定规则重新排序

输入约束条件

  • 字符范围:大小写字母、数字和空格
  • 字符串长度:1-1000个字符
  • 输出要求:单词间单空格分隔,首尾无空格

注意:题目中的"字典序"指的是ASCII码顺序,即数字<大写字母<小写字母。例如"aB1"排序后应为"1Ba"

2. 核心算法设计与实现

2.1 单词内部排序实现

首先我们需要将字符串按空格分割成单词列表,然后对每个单词进行内部字符排序。这里有几个技术要点:

def sort_word(word): # 将单词转为字符列表并排序 return ''.join(sorted(word))

关键细节

  1. sorted()函数默认按ASCII码升序排列
  2. 数字0-9的ASCII码是48-57
  3. 大写字母A-Z是65-90
  4. 小写字母a-z是97-122

2.2 单词统计与排序规则

这部分是本题的核心难点,需要实现三级排序规则:

  1. 主排序:按单词出现频率降序
  2. 次级排序:频率相同时按单词长度升序
  3. 三级排序:前两者都相同时按字典序升序
from collections import defaultdict def process_string(s): # 分割字符串并处理每个单词 words = [sort_word(w) for w in s.split()] # 统计词频 freq = defaultdict(int) for w in words: freq[w] += 1 # 实现三级排序 sorted_words = sorted(words, key=lambda w: (-freq[w], len(w), w)) # 去重并保持顺序 seen = set() result = [] for w in sorted_words: if w not in seen: result.extend([w] * freq[w]) seen.add(w) return ' '.join(result)

算法复杂度分析

  • 时间复杂度:O(n*m log m) + O(n log n),其中n是单词数,m是平均单词长度
  • 空间复杂度:O(n)用于存储词频和结果

3. 边界条件与特殊测试用例

在实际编码中,我发现以下几个边界情况需要特别注意:

  1. 全相同单词:如输入"a a a",输出应为"a a a"
  2. 大小写敏感:"Ab"和"ab"视为不同单词
  3. 数字与字母混合:"a1"排序后应为"1a"
  4. 单字符单词:如输入"a b c b",输出应为"b b a c"
  5. 前导/后缀空格:虽然题目说明用空格分隔,但最好先strip()

测试用例表:

输入预期输出说明
"hello world""ehllo dlorw"基础用例
"a A b B a""a a A B b"大小写敏感
"123 321 123""123 123 123"数字处理
"tree loves coding""eert celov cdgino"多单词场景

4. 性能优化与实用技巧

4.1 使用生成器减少内存占用

对于大字符串,可以改用生成器表达式:

words = (sort_word(w) for w in s.strip().split())

4.2 合并相同单词的排序

观察到相同单词会被多次排序,可以优化:

unique_words = set(words) sorted_unique = sorted(unique_words, key=lambda w: (-freq[w], len(w), w))

4.3 使用Counter替代defaultdict

Python的collections.Counter更简洁:

from collections import Counter freq = Counter(words)

5. 完整实现与测试

最终优化后的完整解决方案:

from collections import Counter def string_reorder(s): def sort_word(w): return ''.join(sorted(w)) words = [sort_word(w) for w in s.strip().split()] freq = Counter(words) # 获取去重单词并按规则排序 unique_words = sorted(freq.keys(), key=lambda w: (-freq[w], len(w), w)) # 重建结果列表 result = [] for w in unique_words: result.extend([w] * freq[w]) return ' '.join(result) # 测试用例 test_cases = [ ("hello world", "ehllo dlorw"), ("a A b B a", "a a A B b"), ("123 321 123", "123 123 123"), ("tree loves coding", "eert celov cdgino"), ("a b c b", "b b a c") ] for input_str, expected in test_cases: assert string_reorder(input_str) == expected

6. 常见问题与调试技巧

Q1:为什么我的排序结果不符合预期?A:检查三级排序规则的实现顺序是否正确:

  1. 先按频率降序
  2. 再按长度升序
  3. 最后按字典序升序

Q2:遇到内存不足错误怎么办?A:对于超长字符串:

  1. 使用生成器替代列表
  2. 分批处理单词
  3. 考虑使用更高效的数据结构如Trie

Q3:如何处理带标点的字符串?A:本题明确限定字符范围,但实际开发中应先清洗数据:

import re clean_s = re.sub(r'[^a-zA-Z0-9 ]', '', s)

调试技巧

  1. 打印中间变量检查处理过程
  2. 对每个排序阶段单独测试
  3. 使用pdb设置断点调试

7. 算法扩展与变种思考

这道题目可以有多种变体,考察不同的能力:

  1. 大小写不敏感版本
words = [sort_word(w.lower()) for w in s.split()]
  1. 保留原始顺序的稳定排序: 需要使用enumerate记录原始位置作为最后一级排序键

  2. 多分隔符处理

import re words = [sort_word(w) for w in re.split(r'[\s,;]+', s)]
  1. 并行化处理: 对于超长字符串,可以用multiprocessing并行处理单词

在实际面试中,完成基础实现后,可以主动讨论这些变体问题的解决方案,展示思维广度。我建议平时练习时,对每道题目都思考可能的变体,这样在面试中就能从容应对考官的追问。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询