Algorithms—127.Word Ladder

本文介绍了一种使用广度优先遍历算法解决单词阶梯问题的方法,通过逐位替换目标字符串来减少时间复杂度,从O(n^2)降低到O(n),并详细解释了算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:因为路径可能循环,如果采用深度优先遍历,则要考虑路径回头的判定,这个不管是时间复杂度还是空间复杂度开销巨大(每条路都要走到死且在走的过程中要记住所有曾经走过的路线)。所以采用广度优先遍历。但是不断地超时,百度了下超时的原因,原来采用的比较相邻(只差一个字母)的方法是逐位比较两个字符串,然后将结果记录在map中,如果字典(wordList)中的元素是n个,则该方法的时间复杂度是O(n^2),所以改为采取逐位替换法,对目标字符串进行逐位替换,判断该字母是否在set中,这样的时间复杂度只有O(n)。广度优先遍历尝试次数为字典元素的个数,因为最坏的情况无非是每次走一步走完整个字典。

论证如下:

设字典元素共有n个,每个长度为l;

直接比较,结果记录,总共比较的次数是(n^2)/2,每次比较的时间是l/2,所以时间复杂度是O(n^2),另外还有O(n^2)空间开销

逐位比较,每个字符串比较的次数是26*l,比较n个,所以时间复杂度是O(n)。

另外,对于该题而言,有时候思路对了依然报超时,仅仅是因为代码的BUG而非是思路真的超时了。用题例的数据检测下你的方法是否能跑出正确答案。如果能,那么才是真的超时。。

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
    	if (beginWord==null||endWord==null||wordList==null||beginWord.equals(endWord)||beginWord.length()!=endWord.length()) {
			return 0;
		}
    	Map<String,List<String>> map=new HashMap<String, List<String>>();
    	int count=1;
    	wordList.add(beginWord);
    	wordList.add(endWord);
    	for (String str:wordList) {
    		count++;
			List<String> list=new ArrayList<String>();
			char[] cs=str.toCharArray();
			for (int i = 0; i < cs.length; i++) {
				char k=cs[i];
				for (char j = 'a'; j <='z'; j++) {
					if (j!=k) {
						cs[i]=j;
						String test=String.valueOf(cs);
						if (wordList.contains(test)) {
							list.add(test);
						}
					}
				}
				cs[i]=k;
			}
			map.put(str, list);
		}
    	Map<String,Integer> test=new HashMap<String, Integer>();
    	test.put(beginWord, 1);
    	for (int i = 1; i < count; i++) {
    		Map<String,Integer> newTest=new HashMap<String, Integer>();
			for (String str:test.keySet()) {
				List<String> list=map.get(str);
				for (int j = 0; j < list.size(); j++) {
					String k=list.get(j);
					if (k.equals(endWord)) {
						return i+1;
					}
					if (test.get(k)==null&&newTest.get(k)==null) {
						newTest.put(k, 1);
					}
				}
			}
			test=newTest;
		}
    	return 0;
    }
}



### algorithms.eaSimple 参数详解 `algorithms.eaSimple` 是 DEAP 框架中用于实现简单遗传算法的一个函数。以下是该函数各参数的具体含义及其用法: #### 函数签名 ```python resultPop, logbook = algorithms.eaSimple( pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=200, stats=None, halloffame=None, verbose=True ) ``` --- #### 参数说明 1. **pop**: 表示初始种群(population)。这是一个由个体组成的列表,其中每个个体是一个基因型表示的对象。通常通过 `toolbox.population()` 方法生成[^2]。 2. **toolbox**: 这是一个工具箱对象,包含了定义算法所需的各种操作符(如交叉、变异、评估等)。这些操作符可以通过注册到 `base.Toolbox` 中完成配置。例如: ```python from deap import base, creator toolbox = base.Toolbox() toolbox.register("evaluate", evaluate_function) toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) ``` 3. **cxpb (Crossover Probability)**: 定义了两个父代个体之间发生交叉的概率。取值范围为 `[0, 1]`,默认值为 `0.5`。较高的概率会增加种群多样性[^2]。 4. **mutpb (Mutation Probability)**: 定义了一个个体发生变异的概率。同样取值范围为 `[0, 1]`,默认值为 `0.2`。较低的突变率有助于保持解的质量,而较高则可以探索更多可能性[^2]。 5. **ngen (Number of Generations)**: 遗传算法运行的最大迭代次数(即世代数),默认值为 `200`。此参数决定了算法终止的时间点。 6. **stats (Statistics Object)**: 可选参数,用于记录每一代统计信息的对象。如果提供,则会在日志中显示诸如平均适应度、标准差等指标。创建方式如下: ```python from deap import tools stats = tools.Statistics(key=lambda ind: ind.fitness.values) stats.register("avg", numpy.mean) stats.register("std", numpy.std) stats.register("min", numpy.min) stats.register("max", numpy.max) ``` 7. **halloffame (HallOfFame Object)**: 可选参数,用于存储历史最优解集合的对象。它可以保存一定数量的最佳个体以便后续分析或输出。 8. **verbose (Verbosity Level)**: 控制是否打印每一代的日志信息,默认值为 `True`。当设置为 `False` 时,不会有任何控制台输出[^2]。 --- #### 返回值 - **resultPop**: 经过指定代数演化后的最终种群。 - **logbook**: 记录了整个演化进程的数据结构,包含每一代的相关统计数据(如果有启用 `stats` 和 `verbose` 的话)。 --- #### 使用示例 以下是一个完整的例子展示如何调用 `eaSimple` 并观察其行为: ```python import random from deap import base, creator, tools, algorithms # 创建适配器类 creator.create("FitnessMax", base.Fitness, weights=(1.0,)) creator.create("Individual", list, fitness=creator.FitnessMax) # 初始化工具箱 toolbox = base.Toolbox() # 属性生成器 toolbox.register("attr_bool", random.randint, 0, 1) # 结构初始化器 toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, 100) toolbox.register("population", tools.initRepeat, list, toolbox.individual) # 注册评价函数 def evalOneMax(individual): return sum(individual), toolbox.register("evaluate", evalOneMax) toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) toolbox.register("select", tools.selTournament, tournsize=3) # 设置其他参数 pop = toolbox.population(n=300) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", lambda values: sum(values) / len(values)) stats.register("min", min) stats.register("max", max) # 执行 eaSimple 算法 result_pop, logbook = algorithms.eaSimple( pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=40, stats=stats, halloffame=hof, verbose=True ) print(f"Best individual is {hof[0]} with a fitness value of {hof[0].fitness.values}") ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值