Skip to content

Commit

Permalink
Added World Ladder problem I and II
Browse files Browse the repository at this point in the history
  • Loading branch information
Amisha328 authored and ErickSimoes committed Oct 29, 2022
1 parent 06d4395 commit 6eeb16f
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 0 deletions.
89 changes: 89 additions & 0 deletions Word Ladder/Word_Ladder_I.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Word Ladder I
// Problem statement:
/*
Given two distinct words startWord and targetWord, and a list denoting wordList of unique words of equal lengths. Find the length of the shortest transformation sequence from startWord to targetWord.
Keep the following conditions in mind:
-> A word can only consist of lowercase characters.
-> Only one letter can be changed in each transformation.
-> Each transformed word must exist in the wordList including the targetWord.
-> startWord may or may not be part of the wordList.
If no possible way to transform sequence from startWord to targetWord return 0.
*/
// Test Case:

/*
Input:
wordList = {"des","der","dfr","dgt","dfs"}
startWord = "der", targetWord= "dfs",
Output:
3
Explanation:
The length of the smallest transformation
sequence from "der" to "dfs" is 3
i,e "der" -> "dfr" -> "dfs".
*/

#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
// TC -> O(N) [wordList length] * O(word length) * O(26) * O(logN) [set]
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
queue<pair<string, int>> q;
// converting vector of wordList to set of wordList
// because it is easier to search as word in set then in a vector
unordered_set<string> s(wordList.begin(), wordList.end());

q.push({beginWord, 1}); // holds the beginning word and initial step as 1

// we are deleting the already traversed word because forming the same word again
// has no point, we want to form the new words and not loop witing the same set of words
s.erase(beginWord);

while(!q.empty()){
string word = q.front().first;
int steps = q.front().second;
q.pop();
if(word == endWord) return steps;

// traverse through all the characters of the word
for(int i = 0; i < word.size(); i++){

string original = word;

// change each character to some different letters from a-z
for(char ch = 'a'; ch <= 'z'; ch++)
{
word[i] = ch;

// if any of the word exist in wordList we will take that word
if(s.count(word)){
s.erase(word);
q.push({word, steps+1});
}
}
word = original; // undo the changes made.
}
}
return 0;
}
};
int main(){
int tc;
cin >> tc;
while(tc--){
int n;
cin >> n;
vector<string>wordList(n);
for(int i = 0; i < n; i++)cin >> wordList[i];
string startWord, targetWord;
cin >> startWord >> targetWord;
Solution obj;
int ans = obj.ladderLength(startWord, targetWord, wordList);
cout << ans << "\n";
}
return 0;
}
126 changes: 126 additions & 0 deletions Word Ladder/Word_Ladder_II.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Word Ladder II
// Problem statement:
/*
Given two distinct words startWord and targetWord, and a list denoting wordList of unique words of equal lengths. Find all shortest transformation sequence(s) from startWord to targetWord. You can return them in any order possible.
Keep the following conditions in mind:
-> A word can only consist of lowercase characters.
-> Only one letter can be changed in each transformation.
-> Each transformed word must exist in the wordList including the targetWord.
-> startWord may or may not be part of the wordList.
-> Return an empty list if there is no such transformation sequence.
*/

// Test Case:
/*
Input:
startWord = "der", targetWord = "dfs",
wordList = {"des","der","dfr","dgt","dfs"}
Output:
der dfr dfs
der des dfs
Explanation:
The length of the smallest transformation is 3.
And the following are the only two ways to get
to targetWord:-
"der" -> "des" -> "dfs".
"der" -> "dfr" -> "dfs".
*/

#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
vector<vector<string>> findSequences(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> st(wordList.begin(), wordList.end());
queue<vector<string>> q;
q.push({beginWord});
// stores used words from wordList of previous level
vector<string> usedOnLevel;
usedOnLevel.push_back(beginWord);
int level = 0;
vector<vector<string>> ans;
while(!q.empty())
{
// stores the current level word sequence
vector<string> v = q.front();
q.pop();

// erase all the words that has been
// used in the previous level to transform
while(v.size() > level)
{
level++;
for(auto it: usedOnLevel)
st.erase(it);
}

string word = v.back();
if(word == endWord)
ans.push_back(v);
for(int i = 0; i < word.size(); i++)
{
char original = word[i];
for(char ch = 'a'; ch <= 'z'; ch++){
word[i] = ch;
if(st.count(word))
{
// if transformed word exists in wordList
// add it to the sequence
v.push_back(word);
q.push(v);

// mark the word as visited on that level
usedOnLevel.push_back(word);
// undo the changes made in word sequenece
// so that it can be changed to some other word
// on the same level
v.pop_back();
}
}
word[i] = original; // undo the character changes
}
}
return ans;
}
};
bool comp(vector<string> a, vector<string> b)
{
string x = "", y = "";
for(string i: a)
x += i;
for(string i: b)
y += i;

return x<y;
}
int main(){
int tc;
cin >> tc;
while(tc--){
int n;
cin >> n;
vector<string>wordList(n);
for(int i = 0; i < n; i++)cin >> wordList[i];
string startWord, targetWord;
cin >> startWord >> targetWord;
Solution obj;
vector<vector<string>> ans = obj.findSequences(startWord, targetWord, wordList);
if(ans.size()==0)
cout<<-1<<endl;
else
{
sort(ans.begin(), ans.end(), comp);
for(int i=0; i<ans.size(); i++)
{
for(int j=0; j<ans[i].size(); j++)
{
cout<<ans[i][j]<<" ";
}
cout<<endl;
}
}
}
return 0;
}

0 comments on commit 6eeb16f

Please sign in to comment.