方法一:BFS
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
| class Solution { public: string plusOne(string s,int i){ if(s[i] == '9')s[i] = '0'; else s[i] = s[i] + 1; return s; } string minusOne(string s,int i){ if(s[i] == '0')s[i] = '9'; else s[i] = s[i] - 1; return s; } set<string>visited; int openLock(vector<string>& deadends, string target) { queue<string>q; q.push("0000"); visited.insert("0000"); for(auto&s : deadends){ if(s == "0000")return -1; visited.insert(s); } int step = 0; while(!q.empty()){ int size = q.size(); while(size--){ string cur = q.front(); q.pop(); if(cur == target)return step; for(int i = 0;i < 4;i++){ string up = plusOne(cur, i); string down = minusOne(cur, i); if(visited.find(up) == visited.end()){ q.push(up); visited.insert(up); } if(visited.find(down) == visited.end()){ q.push(down); visited.insert(down); } } } step++; } return -1; } };
|
方法二:双向BFS
传统的 BFS 框架就是从起点开始向四周扩散,遇到终点时停止;而双向 BFS 则是从起点和终点同时开始扩散,当两边有交集的时候停止。
双向 BFS 也有局限,因为你必须知道终点在哪里。
双向 BFS 还是遵循 BFS 算法框架的,只是不再使用队列,而是使用 set 方便快速判断两个集合是否有交集。
另外的一个技巧点就是 while 循环的最后交换 q1
和 q2
的内容,所以只要默认扩散 q1
就相当于轮流扩散 q1
和 q2
。
其实双向 BFS 还有一个优化,就是在 while 循环开始时做一个判断:
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
| class Solution { public: string plusOne(string s,int i){ if(s[i] == '9')s[i] = '0'; else s[i] = s[i] + 1; return s; } string minusOne(string s,int i){ if(s[i] == '0')s[i] = '9'; else s[i] = s[i] - 1; return s; } set<string>visited; int openLock(vector<string>& deadends, string target) { set<string>s1; s1.insert("0000"); visited.insert("0000"); for(auto&s : deadends){ if(s == "0000")return -1; visited.insert(s); } set<string>s2; s2.insert(target); int step = 0;
while(!s1.empty() && !s2.empty()){ set<string>temp; for(auto cur : s1){ if(s2.find(cur) != s2.end())return step; visited.insert(cur); for(int i = 0;i < 4;i++){ string up = plusOne(cur, i); string down = minusOne(cur, i); if(visited.find(up) == visited.end())temp.insert(up); if(visited.find(down) == visited.end())temp.insert(down); } } step++; s1 = s2; s2 = temp; }
return -1; } };
|
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
| class Solution { public: bool check(string s,string t){ int len = s.length(); int cnt = 0; for(int i = 0;i < len;i++){ if(s[i] != t[i])cnt++; } return cnt == 1; } int ladderLength(string beginWord, string endWord, vector<string>& wordList) { unordered_set<string> wordSet(wordList.begin(), wordList.end()); if(wordSet.find(endWord) == wordSet.end())return 0; unordered_set<string>s1;s1.insert(beginWord); unordered_set<string>s2;s2.insert(endWord); unordered_set<string>visited;
int step = 1; while(!s1.empty()&&!s2.empty()){ if (s1.size() > s2.size()) { swap(s1,s2); } unordered_set<string>temp; for(auto cur : s1){ if(s2.find(cur)!=s2.end())return step; visited.insert(cur); for(auto word : wordList){ if(check(word, cur) && visited.find(word) == visited.end()){ temp.insert(word); } } } step++; s1 = s2; s2 = temp; } return 0; } };
|