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

如何从已排序字符串顶点列表高效生成边(不修改数据结构)

高效生成单词顶点边的优化方案

问题背景

给定已排序的字符串顶点列表,要求不修改现有数据结构,寻找比两层嵌套循环更高效的边生成方式。当前使用的两层循环代码如下:

for word in vertices:
    for other_word in vertices:
        # 检查顶点是否连通并添加边
        weight = get_weight(word, other_word)
        if weight != -1:
            # 添加边

曾尝试跳过重复顶点对的优化,但面对大规模数据时性能依旧很差:

for word in vertices:
    for other_word in vertices:
        if other_word <= word:
            continue
        else:
            # 检查顶点是否连通并添加边

补充说明:判断顶点连通性的get_weight函数逻辑如下(本次重点不在优化该函数本身):

def get_weight(word1, word2):
    weight = -1
    if isAnagram(word1, word2):
        weight = 1
    elif one_letter_diff(word1, word2):
        weight = 2
    # 其他判断逻辑
    return weight

最终目标是通过Dijkstra算法计算指定两单词间的最短路径。

优化方案

1. 变位词分组预处理,减少重复判断

变位词的核心特征是字符组成完全一致,先遍历一次顶点列表,将所有变位词归类到同一组:

from collections import defaultdict

anagram_groups = defaultdict(list)
for word in vertices:
    # 以排序后的字符串作为键,确保变位词的键完全相同
    key = ''.join(sorted(word))
    anagram_groups[key].append(word)

同一组内的所有单词两两之间权重为1,直接生成组内的边即可,无需再调用isAnagram做重复判断,能大幅减少无效计算。

2. 掩码模式匹配,快速定位单字母差异单词

针对单字母差异的场景,可通过生成“模糊掩码模式”构建映射表:

pattern_map = defaultdict(list)
# 假设所有单词长度一致,若长度不同可先按长度分组再处理
word_length = len(vertices[0])

for word in vertices:
    for i in range(word_length):
        # 将单词的每个位置替换为通配符*,生成对应的模式
        pattern = word[:i] + '*' + word[i+1:]
        pattern_map[pattern].append(word)

处理每个单词时,遍历其所有掩码模式,从pattern_map中取出对应的单词列表,这些单词就是与当前单词单字母差异的候选,直接生成权重为2的边即可,避免了与所有单词逐一比对。

3. 结合有序列表特性,用二分查找加速匹配

利用顶点列表已排序的特点,对单字母差异的候选单词进行二分查找,快速验证是否存在于列表中:

import bisect

alphabet = 'abcdefghijklmnopqrstuvwxyz'
word_length = len(vertices[0])

for word in vertices:
    for i in range(word_length):
        original_char = word[i]
        for c in alphabet:
            if c == original_char:
                continue
            # 生成单字母替换后的候选单词
            candidate = word[:i] + c + word[i+1:]
            # 二分查找判断候选是否存在于顶点列表
            idx = bisect.bisect_left(vertices, candidate)
            if idx < len(vertices) and vertices[idx] == candidate:
                # 生成权重为2的边
                pass

这种方式跳过了大量不可能匹配的单词,比全量遍历效率提升显著。

4. 延迟加载边,按需生成

既然最终要执行Dijkstra算法,无需提前生成所有边。可在Dijkstra遍历过程中,处理当前单词时再通过上述方法找出所有连通单词,作为邻接节点加入优先级队列。这种方式既节省内存,又避免了预处理所有边的时间开销,在顶点数量极大的场景下优势尤为明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:07:13