go语言刷题:127. 单词接龙

题目

字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk:

每一对相邻的单词只差一个字母。
对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
sk == endWord
给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。

示例 1:

输入:beginWord = “hit”, endWord = “cog”, wordList =
[“hot”,“dot”,“dog”,“lot”,“log”,“cog”] 输出:5 解释:一个最短转换序列是 “hit” -> “hot”
-> “dot” -> “dog” -> “cog”, 返回它的长度 5。

示例 2:

输入:beginWord = “hit”, endWord = “cog”, wordList =
[“hot”,“dot”,“dog”,“lot”,“log”] 输出:0 解释:endWord “cog” 不在字典中,所以无法进行转换。

代码:

// 建立映射关系
func getWordMap(wordList []string, beginWord string) map[string]int {
	// 创建字母和数字的映射关系
	wordMap := make(map[string]int)
	// 遍历单词列表,和数字建立联系
	for i, word := range wordList {
		// 如果该字母已经存在已经有的映射关系,则不重复建立映射关系
		// 如果该字母不存在没有建立映射关系,则新建立映射关系
		if _, ok := wordMap[word]; !ok {
			if word != beginWord {
				wordMap[word] = i
			}
		}
	}
	return wordMap
}

// 列举可能的情况
func getCandidates(word string) []string {
	var res []string
	// 遍历26个英文字母
	for i := 0; i < 26; i++ {
		// 因为word的长度不止一个,因此遍历多个字母的情况,插入单词的不同位置
		for j := 0; j < len(word); j++ {
			// 如果列举的字符不是当前字符,则将该字符添加进列表中
			if byte(int('a')+i) != word[j] {
				res = append(res, word[:j]+string(rune(int('a')+i))+word[j+1:])
			}
		}
	}
	return res
}

// https://leetcode-cn.com/problems/word-ladder/description/
func ladderLength(beginWord string, endWord string, wordList []string) int {
	// 创建映射关系列表,beginWord字符串列表,节点数量
	wordMap, beginwordlist, count := getWordMap(wordList, beginWord), []string{beginWord}, 0
	// 如果beginword不为空,则执行以下逻辑
	// 如果beginword为空,则返回0
	for len(beginwordlist) > 0 {
		// 初始化转换序列长度,长度为1,代表beginWord本身,即beginWord->
		count++
		// 初始化beginWord长度
		beginwordlen := len(beginwordlist)
		// 遍历开始的字符串
		for i := 0; i < beginwordlen; i++ {
			// 初始化首个字符
			word := beginwordlist[0]
			// 更新字符串列表
			beginwordlist = beginwordlist[1:]
			// 获取所有可能的情况
			candidates := getCandidates(word)
			// 遍历所有可能的情况
			for _, candidate := range candidates {
				// 如果该种情况的单词在映射列表里
				if _, ok := wordMap[candidate]; ok {
					// 如果该种情况的单词=目标单词,则返回2,表示从beginWord可以直接到endWord
					if candidate == endWord {
						// 直接返回2
						return count + 1
					}
					// 如果是该种情况的单词!= 目标单词,删除该种情况下的单词
					delete(wordMap, candidate)
					// 将该种情况下的单词重新添加进beginwordlist进行后续循环
					beginwordlist = append(beginwordlist, candidate)
				}
			}
		}
	}
	return 0
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值