17、单词接龙

题目描述:
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:

如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 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” 不在字典中,所以无法进行转换。

比较简单的BFS算法,但是你需要注意的是防止出现死循环,因此我设置了 一个Set集合,用于存储的是所有节点,所谓BFS指的是宽度优先搜索,设置一个队列,存放的是一行行的值,isOneDif是取出所有与该节点只有一个字符之差的字符,代码如下

class Solution {
     public boolean isOnDif(String s,String  t){
		int dif = 0;
		for (int i = 0; i < s.length(); i++) {
			if(s.charAt(i) != t.charAt(i)){
				dif++;
			}
			if(dif > 1 ){
				return false;
			}
		}
		return dif == 1;
	}
	public int ladderLength(String beginWord, String endWord, List<String> wordList) {
	//如果不包含那么就返回0
        if(!wordList.contains(endWord)){
        	return 0;
        }
        int deep = 1;
        Queue<String> temQueue = new LinkedList<>();
        Set<String> temSet = new HashSet<>();
        temSet.add(beginWord);
        temQueue.offer(beginWord);
        while (!temQueue.isEmpty()) {
			int size = temQueue.size();
			deep ++;
			while (size > 0) {
				size--;
				String temString = temQueue.poll();
				//取出第一层,然后我们开始寻找与之只有一个字母的区别的字母
				for (String string : wordList) {
					if(isOnDif(temString, string) && !temSet.contains(string)){
						if(string.equals(endWord)){
							return deep;
						}
						temSet.add(string);
						temQueue.offer(string);
					}
					
				}
			}
		}
        
        return 0;
    }

}

很显然排名不会很高,因为差不多使用的是暴力搜索,因此考虑优化
使用两头递归的方法,即:设置一个set为beginset保存的是一开始的初始单词设置一个set为endset为目的单词,worddic为给出的单词列表,其中也是set,一开始从beginset开始,设置一个temset,从beginset中寻找与之差一位的单词放入temset中,改进的代码思路:
从两边开始查找,每次都从比较小的开始寻找
自己实现的代码如下

class Solution {
   public boolean isOnDif(String s,String  t){
			int dif = 0;
			for (int i = 0; i < s.length(); i++) {
				if(s.charAt(i) != t.charAt(i)){
					dif++;
				}
				if(dif > 1 ){
					return false;
				}
			}
			return dif == 1;
		}
		public int ladderLength(String beginWord, String endWord, List<String> wordList) {
			if(!wordList.contains(endWord)){
				return 0;
			}
			
			Set<String> beginSet = new HashSet<>(Arrays.asList(beginWord));
			Set<String> endSet = new HashSet<>(Arrays.asList(endWord));
			Set<String> dic = new HashSet<>(wordList);
			int step = 1;
			while (!beginSet.isEmpty()) {
				step++;
				Set<String> temSet = new HashSet<>();
				for (String string : beginSet) {
					//在字典中删除beginset中包含的
					dic.remove(string);
				}
				for (String string : beginSet) {
					//相差一个,并且在dic中
					for (String strings : dic) {
						if(isOnDif(string, strings)){
							temSet.add(strings);
							if(endSet.contains(strings)){
								return step;
							}
						}
					}
				}
				if(temSet.size() < endSet.size()){
					beginSet = temSet;
				}else {
					beginSet = endSet;
					endSet = temSet;
				}
			}
			
			return 0;
}}

排名靠前的代码

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> beginSet = new HashSet<>();
        Set<String> endSet = new HashSet<>();
        beginSet.add(beginWord);
        endSet.add(endWord);
        Set<String> dict = new HashSet<>(wordList);
        if(!dict.contains(endWord)) return 0;
        return bfs(beginSet, endSet, dict, 0);
    }
    
    private int bfs(Set<String> beginSet, Set<String> endSet, Set<String> dict, int step){
        if(beginSet.isEmpty() || endSet.isEmpty()) return 0;
        step++;
        dict.removeAll(beginSet);
        Set<String> nextSet = new HashSet<>();
        for(String str : beginSet){
            char[] chs = str.toCharArray();
            for(int i = 0; i < chs.length; i++){
                char old = chs[i];
                for(char c = 'a'; c <= 'z'; c++){
                    chs[i] = c;
                    String next = new String(chs);
                    if(!dict.contains(next)) continue;
                    if(endSet.contains(next)) return step + 1;
                    nextSet.add(next);
                }
                chs[i] = old;
            }
        }
        return nextSet.size() > endSet.size() ? bfs(endSet, nextSet, dict, step) : bfs(nextSet, endSet, dict, step);
    }
}

看一下这位同志的思路
在这里插入图片描述
借用的就是这个思路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单词接龙是一个游戏,旨在通过更改一个字母来逐步转换一个单词成为另一个指定的单词。规则包括: 1. 可用于接龙单词首字母必须与前一个单词的尾字母相同。 2. 当存在多个首字母相同的单词时,取长度最长的单词。如果长度也相等,则取词典序最小的单词。 3. 已经参与接龙单词不能重复使用。 对于给定的一组由小写字母组成的单词数组和指定的起始单词和结束单词,我们需要进行单词接龙,并输出最长的单词串,其中单词串是由单词拼接而成,中间没有空格。如果不存在这样的转换序列,则返回0。 例如,对于输入的例子 beginWord = "hit",endWord = "cog",wordList = ["hot", "dot", "dog", "lot", "log"],我们可以进行以下单词接龙序列: "hit" -> "hot" -> "dot" -> "dog" -> "cog"。在这个例子中,最长的单词串为"hit" -> "hot" -> "dot" -> "dog" -> "cog"。 请注意,以上例子只是为了说明单词接龙的概念和规则,并不是针对Python编程的具体实现。具体的实现方法可以使用广度优先搜索 (BFS) 或双向BFS等算法来解决。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python题目55:单词接龙](https://blog.csdn.net/m0_60741207/article/details/121528418)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [127. 单词接龙(Python)](https://blog.csdn.net/JulyLi2019/article/details/106610034)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值