-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathword_ladder.rb
56 lines (50 loc) · 1.48 KB
/
word_ladder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# https://leetcode.com/problems/word-ladder/
#
# Given two words (beginWord and endWord), and a dictionary's word list, find
# the length of shortest transformation sequence from beginWord to endWord,
# such that:
#
# + Only one letter can be changed at a time
# + 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.
# @param {String} begin_word
# @param {String} end_word
# @param {Set<String>} word_list
# @return {Integer}
def ladder_length(begin_word, end_word, word_list)
_ladder_length_(
Hash(begin_word => true),
Hash(end_word => true),
Marshal.load(Marshal.dump(word_list)), 1
)
end
private def _ladder_length_(ws1, ws2, words, steps)
return _ladder_length_(ws2, ws1, words, steps) if ws1.size > ws2.size
return 0 if ws1.size == 0
nextws1 = {}
ws1.keys.map(&:dup).each do |w|
w.chars.each_with_index do |ch, idx|
Range.new('a', 'z').each do |newch|
w[idx] = newch
return steps + 1 if ws2.key?(w)
nextws1[w] = true if words.delete?(w)
end
w[idx] = ch
end
end
_ladder_length_(nextws1, ws2, words, steps + 1)
end