Skip to content

refactor: WordLadder #5434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 24 additions & 54 deletions src/main/java/com/thealgorithms/strings/WordLadder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,28 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;

/*
**Problem Statement:**
A transformation sequence from word beginWord to word endWord using a dictionary wordList is a
sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:

Every adjacent pair of words differs by a single letter.
Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
sk == endWord
Given two words, beginWord and endWord, and a dictionary wordList, return the number of words in
the shortest transformation sequence from beginWord to endWord, or 0 if no such sequence exists.

**Example 1:**
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: One shortest transformation sequence is "hit" -> "hot" -> "dot" -> "dog" -> cog",
which is 5 words long.

**Example 2:**
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore there is no valid transformation
sequence.

**Constraints:**
1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord, endWord, and wordList[i] consist of lowercase English letters.
beginWord != endWord
All the words in wordList are unique.
/**
* Class to find the shortest transformation sequence from a beginWord to an endWord using a dictionary of words.
* A transformation sequence is a sequence of words where each adjacent pair differs by exactly one letter.
*/

final class WordLadder {
public final class WordLadder {
private WordLadder() {
}

/**
* This function finds the ladderLength
* Finds the shortest transformation sequence from beginWord to endWord.
*
* @param beginWord: Starting word of the ladder
* @param endWord: Ending word of the ladder
* @param wordList: This list contains the words which needs to be included
* in ladder.
* @return ladderLength: This function will return the ladderLength(level)
* if the endword is there. Otherwise, will return the length as 0.
* @param beginWord the starting word of the transformation sequence
* @param endWord the target word of the transformation sequence
* @param wordList a list of words that can be used in the transformation sequence
* @return the number of words in the shortest transformation sequence, or 0 if no such sequence exists
*/
public static int ladderLength(String beginWord, String endWord, List<String> wordList) {
HashSet<String> set = new HashSet<>(wordList);
Set<String> wordSet = new HashSet<>(wordList);

if (!set.contains(endWord)) {
if (!wordSet.contains(endWord)) {
return 0;
}

Expand All @@ -66,25 +36,25 @@ public static int ladderLength(String beginWord, String endWord, List<String> wo
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
String curr = queue.poll();
char[] wordsChars = curr.toCharArray();
for (int j = 0; j < wordsChars.length; j++) {
char originalChars = wordsChars[j];
String currentWord = queue.poll();
char[] currentWordChars = currentWord.toCharArray();
for (int j = 0; j < currentWordChars.length; j++) {
char originalChar = currentWordChars[j];
for (char c = 'a'; c <= 'z'; c++) {
if (wordsChars[j] == c) {
if (currentWordChars[j] == c) {
continue;
}
wordsChars[j] = c;
String transformedWord = String.valueOf(wordsChars);
if (transformedWord.equals(endWord)) {
currentWordChars[j] = c;
String newWord = new String(currentWordChars);

if (newWord.equals(endWord)) {
return level + 1;
}
if (set.contains(transformedWord)) {
set.remove(transformedWord);
queue.offer(transformedWord);
if (wordSet.remove(newWord)) {
queue.offer(newWord);
}
}
wordsChars[j] = originalChars;
currentWordChars[j] = originalChar;
}
}
level++;
Expand Down
10 changes: 10 additions & 0 deletions src/test/java/com/thealgorithms/strings/WordLadderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

public class WordLadderTest {

Expand Down Expand Up @@ -38,4 +40,12 @@ public void testWordLadder2() {
List<String> wordList2 = Arrays.asList("hot", "dot", "dog", "lot", "log");
assertEquals(WordLadder.ladderLength("hit", "cog", wordList2), 0);
}

@ParameterizedTest
@CsvSource({"'a', 'c', 'b,c', 2", "'a', 'c', 'a', 0", "'a', 'a', 'a', 0", "'ab', 'cd', 'ad,bd,cd', 3", "'a', 'd', 'b,c,d', 2", "'a', 'd', 'b,c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,d', 2"})
void testLadderLength(String beginWord, String endWord, String wordListStr, int expectedLength) {
List<String> wordList = List.of(wordListStr.split(","));
int result = WordLadder.ladderLength(beginWord, endWord, wordList);
assertEquals(expectedLength, result);
}
}