26. Word Ladder II
题目描述
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
- Return an empty list if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
这道题目可以使用回溯、DFS或者BFS来计算。
代码实现
法一:回溯
这个版本的回溯是会超时的,做过一些改进依然在某些case超时。
class Solution {
public:
int cur_shotest_len = INT_MAX;
__inline int isClose(const string a, const string b, int len) {
int cnt = 0;
while(len--)
if(a[len] != b[len]) cnt++;
return cnt;
}
void backTracking(vector<vector<string>>& res, vector<string>& cur, string beginWord, string endWord, vector<string> wordList, int size, int len, vector<int>& rec, int stt) {
if(isClose(beginWord, endWord, len) == 0) {
if(cur_shotest_len > cur.size())
while(!res.empty()) res.pop_back();
if(cur_shotest_len < cur.size()) return;
cur_shotest_len = cur.size();
res.push_back(cur);
return;
}
for(int i = 0; i < size; i++) {
if(rec[i] == 0 && cur.size() + 1 <= cur_shotest_len && isClose(beginWord, wordList[i], len) == 1) {
rec[i] = 1;
cur.push_back(wordList[i]);
backTracking(res, cur, wordList[i], endWord, wordList, size, len, rec, i+1);
cur.pop_back();
rec[i] = 0;
}
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
int size = wordList.size();
vector<vector<string>> res;
if(!size) return res;
vector<string> cur;
vector<int> rec(size, 0);
int word_len = beginWord.size();
cur.push_back(beginWord);
backTracking(res, cur, beginWord, endWord, wordList, size, word_len, rec, 0);
return res;
}
};
对它改进的一个版本,还有一个case无法通过:
class Solution {
public:
int cur_shotest_len = INT_MAX;
vector<vector<string>> res;
vector<string> cur;
vector<vector<int>> dis;
__inline int isClose(const string a, const string b, int len) {
int cnt = 0;
while(len--)
if(a[len] != b[len]) cnt++;
return cnt;
}
void backTracking(string beginWord, string endWord, vector<string> wordList, int size, int len, int lst) {
if(dis[lst+1][size+1] == 0) {
if(cur_shotest_len > cur.size())
while(!res.empty()) res.pop_back();
if(cur_shotest_len < cur.size()) return;
cur_shotest_len = cur.size();
res.push_back(cur);
return;
}
for(int i = 0; i < size; i++) {
if(cur.size() + 1 <= cur_shotest_len) {
if(dis[lst+1][i+1] == 1) {
cur.push_back(wordList[i]);
backTracking(wordList[i], endWord, wordList, size, len, i);
cur.pop_back();
}
}
}
}
void countDis(int size, int len, string beginWord, string endWord, vector<string> wordList) {
dis[0][size+1] = isClose( beginWord, endWord, len);
dis[size+1][0] = dis[0][size+1];
for(int col = 0; col < size; col++) {
dis[0][col+1] = isClose( beginWord, wordList[col], len);
dis[col+1][0] = dis[0][col+1];
}
for(int row = 0; row < size; row++) {
dis[row+1][size+1] = isClose( endWord, wordList[row], len);
dis[size+1][row+1] = dis[row+1][size+1];
}
for(int row = 0; row < size; row++)
for(int col = row+1; col < size; col++) {
dis[row+1][col+1] = isClose( wordList[col], wordList[row], len);
dis[col+1][row+1] = dis[row+1][col+1];
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
int size = wordList.size();
if(!size) return res;
int word_len = beginWord.size();
dis.resize(size+2);
for(int i = 0; i < size+2; i++) dis[i].resize(size+2, 0);
cur.push_back(beginWord);
cur_shotest_len = size + 2;
countDis(size, word_len, beginWord, endWord, wordList);
backTracking(beginWord, endWord, wordList, size, word_len, -1);
return res;
}
};
上面的优化只是把距离提前计算好,然后调用。但是这个算法的瓶颈在于查找距离为一的过程。
所以需要在这个部分进行优化。
class Solution {
public:
int cur_shotest_len = INT_MAX;
vector<vector<string>> res;
vector<string> cur;
vector<vector<int>> dis;
vector<bool> rec; // with zero
__inline int isClose(const string a, const string b, int len) {
int cnt = 0;
while(len--) if(a[len] != b[len]) cnt++;
return cnt;
}
void backTracking(string beginWord, string endWord, vector<string>& wordList, int size, int len, int lst) {
int range = dis[lst+1].size();
for(int i = 0; i < range; i++) {
if(cur.size() + 1 <= cur_shotest_len) {
cur.push_back(wordList[dis[lst+1][i]-1]);
if(rec[dis[lst+1][i]]) {
if(cur_shotest_len > cur.size())
while(!res.empty()) res.pop_back();
if(cur_shotest_len < cur.size()) { cur.pop_back(); return;}
cur_shotest_len = cur.size();
res.push_back(cur);
cur.pop_back();
return;
}
else
backTracking(wordList[dis[lst+1][i] - 1], endWord, wordList, size, len, dis[lst+1][i]-1);
cur.pop_back();
}
}
}
void countDis(int size, int len, string beginWord, string endWord, vector<string> wordList) {
int tmp = isClose( beginWord, endWord, len);
if(!tmp) rec[0] = true;
for(int col = 0; col < size; col++) {
tmp = isClose( beginWord, wordList[col], len);
if(tmp == 1)
dis[0].push_back(col+1);
}
for(int row = 0; row < size; row++) {
tmp = isClose( endWord, wordList[row], len);
if(!tmp) rec[row+1] = true;
}
for(int row = 0; row < size; row++)
for(int col = row+1; col < size; col++) {
tmp = isClose( wordList[col], wordList[row], len);
if(tmp == 1) {
dis[col+1].push_back(row+1);
dis[row+1].push_back(col+1);
}
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
int size = wordList.size();
if(!size) return res;
int word_len = beginWord.size();
dis.resize(size + 1);
rec.resize(size + 1, false);
cur.push_back(beginWord);
cur_shotest_len = size + 2;
countDis(size, word_len, beginWord, endWord, wordList);
backTracking(beginWord, endWord, wordList, size, word_len, -1);
return res;
}
};
AC的代码参考了:https://discuss.leetcode.com/topic/40902/clean-but-the-best-submission-68ms-in-c-well-commented/2
现在还在优化中。。。
507. Perfect Number
题目描述
We define the Perfect Number is a positive integer that is equal to the sum of all its positive divisors except itself.
Now, given an integer n, write a function that returns true when it is a perfect number and false when it is not.
Example:
Input: 28
Output: True
Explanation: 28 = 1 + 2 + 4 + 7 + 14
Note: The input number n will not exceed 100,000,000. (1e8)
代码实现
class Solution {
public:
bool checkPerfectNumber(int num) {
int half = ceil(sqrt(num)), res = 1;
for(int i = 2; i < half; i++) if(num%i == 0) {
res += i + (num/i);
}
res += ceil(sqrt(num)) == floor(sqrt(num))? half:0;
return res == num;
}
};