127. Word Ladder

本文介绍了一种利用广度优先搜索(BFS)算法求解单词转换最短路径的方法,并通过两种不同的BFS实现方式——单向BFS和双向BFS进行了详细说明。这两种方法能够有效地找到从一个单词到另一个单词的最短转换序列。

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

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence frombeginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the word list

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.

  • All words contain only lowercase alphabetic characters.


BFS,从当前字串出发,下一层的字串有哪些,这个过程如果和集合里面的每一个字串遍历检测,复杂度O(N^2),大数据将超时,需要变换字母构造字串,然后检测构造的字串是不是在单词可用集合里面。

public int ladderLength(String beginWord, String endWord,Set<String> wordList)
	{
		if(beginWord.compareTo(endWord)==0)
			return 0;
		
		wordList.add(endWord);
		wordList.remove(beginWord);
		
		ArrayDeque<String> deque=new ArrayDeque<>();
		HashMap<String, Boolean> hashmap=new HashMap<>(wordList.size());
		for(String ss:wordList)
			hashmap.put(ss, false);
		
		deque.add(beginWord);
		int count=1;
		int level=0;
		while(!deque.isEmpty())
		{
			count--;
			if(count==0)
				{
					level++;
					count=deque.size();
				}
			
			String s=deque.poll();
			if(s.compareTo(endWord)==0)
				return level;
			
			
			int strlen=s.length();
			for(int i=0;i<strlen;i++)
			{
				char c=s.charAt(i);
				StringBuilder sb=new StringBuilder(s);
				for(char cc='a';cc<c;cc++)
				{
					sb.setCharAt(i, cc);
					String temp=sb.toString();
					if(wordList.contains(temp)&&hashmap.get(temp)==false)
						{
							deque.add(temp);
							hashmap.put(temp, true);
						}
				}
				for(char cc=(char) (c+1);cc<='z';cc++)
				{
					sb.setCharAt(i, cc);
					String temp=sb.toString();
					if(wordList.contains(temp)&&hashmap.get(temp)==false)
						{
							deque.add(temp);
							hashmap.put(temp, true);
						}
				}	
			}	
		}
		return 0;
	}


--------------------------------------------------------------------------------------------
双向BFS,速度会有很大提高
https://discuss.leetcode.com/topic/29303/two-end-bfs-in-java-31ms

每次搜索,轮流从beginset和endset进行(104ms)

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
		Set<String> beginSet = new HashSet<String>(), endSet = new HashSet<String>();

		int len = 1;
		int strLen = beginWord.length();
		HashSet<String> visited = new HashSet<String>();
		
		beginSet.add(beginWord);
		endSet.add(endWord);
		boolean change=false;
		while (!beginSet.isEmpty() && !endSet.isEmpty()) 
		{
			if (change) {
				Set<String> set = beginSet;
				beginSet = endSet;
				endSet = set;
			}

			Set<String> temp = new HashSet<String>();
			for (String word : beginSet) {
				char[] chs = word.toCharArray();

				for (int i = 0; i < chs.length; i++) {
					for (char c = 'a'; c <= 'z'; c++) {
						char old = chs[i];
						chs[i] = c;
						String target = String.valueOf(chs);

						if (endSet.contains(target)) {
							return len + 1;
						}

						if (!visited.contains(target) && wordList.contains(target)) {
							temp.add(target);
							visited.add(target);
						}
						chs[i] = old;
					}
				}
			}

			beginSet = temp;
			len++;
			change=!change;
		}
		
		return 0;
	}
}


每次搜索,轮流从beginset和endset选择元素数量较少的进行搜索(30ms)


"The idea behind bidirectional search is to run two simultaneous searches—one forward from
the initial state and the other backward from the goal—hoping that the two searches meet in
the middle. The motivation is that b^(d/2) + b^(d/2) is much less than b^d. b is branch factor, d is depth. 


public class Solution {

public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
	Set<String> beginSet = new HashSet<String>(), endSet = new HashSet<String>();

	int len = 1;
	int strLen = beginWord.length();
	HashSet<String> visited = new HashSet<String>();
	
	beginSet.add(beginWord);
	endSet.add(endWord);
	while (!beginSet.isEmpty() && !endSet.isEmpty()) {
		if (beginSet.size() > endSet.size()) {
			Set<String> set = beginSet;
			beginSet = endSet;
			endSet = set;
		}

		Set<String> temp = new HashSet<String>();
		for (String word : beginSet) {
			char[] chs = word.toCharArray();

			for (int i = 0; i < chs.length; i++) {
				for (char c = 'a'; c <= 'z'; c++) {
					char old = chs[i];
					chs[i] = c;
					String target = String.valueOf(chs);

					if (endSet.contains(target)) {
						return len + 1;
					}

					if (!visited.contains(target) && wordList.contains(target)) {
						temp.add(target);
						visited.add(target);
					}
					chs[i] = old;
				}
			}
		}

		beginSet = temp;
		len++;
	}
	
	return 0;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值