求解修改版单词阶梯问题中到目标节点集最优的起始节点方法
改进版Word Ladder最优起始词求解方案
问题定义
我们需要从给定的等长单词列表中选出最优的first_word,使得它到所有desired_words的最短单词阶梯长度的最大值尽可能小,存在多个符合条件的单词时返回任意一个的索引即可。
示例:给定列表
lst = ["aaa","aad","dad","daa","aca","acc","aab","abb"]构建无向图(两个单词仅一个字符不同则连边,边权为1),若desired_words为dad、abb、acc,最优起始词为aaa,返回索引0;若desired_words为aaa、aca、acc,最优起始词为aca,返回索引4。
算法思路
你之前想到的Jordan中心思路是完全正确的,本题本质是求针对desired_words节点子集的受限图中心,即到所有目标节点的最大最短距离最小的节点。具体实现步骤如下:
- 第一步:高效构建邻接表。用模式掩码法替代逐对单词比较,将每个单词的每个位置替换为通配符生成模式,同一模式下的所有单词两两仅一个字符不同,直接连边即可,大幅降低建图时间。
- 第二步:多轮BFS预处理最短距离。因所有边权为1,不需要用Dijkstra算法,直接用BFS求最短路径即可。且不需要对所有节点跑BFS,仅需要对数量更少的
desired_words逐个跑BFS,记录每个节点到所有目标节点的最短距离,效率更高。 - 第三步:筛选最优节点。遍历所有节点,计算每个节点到所有目标节点的最大距离,选择最大距离最小的节点返回索引即可。
Python代码实现
from collections import defaultdict, deque def find_optimal_start(word_list, desired_words): n = len(word_list) # 建立单词到索引的映射 word_to_idx = {word: idx for idx, word in enumerate(word_list)} desired_idxs = [word_to_idx[w] for w in desired_words] word_len = len(word_list[0]) # 步骤1:构建邻接表 adj = [[] for _ in range(n)] pattern_map = defaultdict(list) for idx, word in enumerate(word_list): for i in range(word_len): # 生成每个位置替换为通配符的模式 pattern = word[:i] + '*' + word[i+1:] pattern_map[pattern].append(idx) # 同模式下的单词两两连边 for group in pattern_map.values(): for i in range(len(group)): for j in range(i+1, len(group)): u, v = group[i], group[j] adj[u].append(v) adj[v].append(u) # 步骤2:预处理每个节点到所有目标节点的最短距离 dist = [[float('inf')] * len(desired_idxs) for _ in range(n)] for d_pos, target_idx in enumerate(desired_idxs): q = deque([target_idx]) dist[target_idx][d_pos] = 0 while q: cur = q.popleft() for neighbor in adj[cur]: if dist[neighbor][d_pos] == float('inf'): dist[neighbor][d_pos] = dist[cur][d_pos] + 1 q.append(neighbor) # 步骤3:找最大距离最小的节点 min_max_dist = float('inf') best_idx = 0 for i in range(n): current_max = max(dist[i]) if current_max < min_max_dist: min_max_dist = current_max best_idx = i return best_idx # 测试用例 if __name__ == "__main__": lst = ["aaa","aad","dad","daa","aca","acc","aab","abb"] # 测试1 desired1 = ["dad", "abb", "acc"] print(find_optimal_start(lst, desired1)) # 输出 0 # 测试2 desired2 = ["aaa", "aca", "acc"] print(find_optimal_start(lst, desired2)) # 输出 4
内容的提问来源于stack exchange,提问作者Python_learner
相关产品推荐
相关产品推荐

