1. 填充每个节点的下一个右侧节点指针II
给定一个二叉树
struct Node
{
int val;
Node* left;
Node* right;
Node* next;
}
填充它的每个next指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将next指针设置为NULL。
初始状态下,所有next指针都被设置为NULL。
思路:因为首先要判断右边的节点,所以要先递归右子树
Node* connect(Node* root) {
if(root == nullptr)
{
return root;
}
Node* p = root -> next;
while(p)
{
if(p -> left)
{
p = p -> left;
break;
}
if(p -> right)
{
p = p -> right;
break;
}
p = p -> next;
}
if(root -> right)
{
root -> right -> next = p;
}
if(root -> left)
{
root -> left -> next = root -> right ? root -> right : p;
}
connect(root -> right);
connect(root -> left);
return root;
}
2. 单词接龙
给定两个单词(beginWord和endWord)和一个词典。找到从beginWord到endWord的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母
- 转换过程中的中间单词必须是字典中的单词
说明:
- 如果不存在这样的转换序列,返回0
- 所有单词具有相同的长度
- 所有单词只由小写字母组成
- 字典中不存在重复的单词
- 可以假设beginWord和endWord是非空的,且二者不相同
思路:最短路径问题,首选BFS
用队列存储经过变换能够得到的单词(在单词表中也出现的),每次取队首元素,遍历其每个字符,将字符以此置换为a~z,判断置换后的新词是否在单词表中存在,如果存在,则将该新词入队,如果新词和最后目标词相同,那么输出长度。循环上述操作,知道队列为空时,如果还没有任何词和目标词相同,那么输出0。
- 如何记录变换序列的长度
通过插入在队列中插入特殊符号“,”,经过以此变换能够到达的单词放在一起,经过两次变换能够到达的单词放在一起,然后通过“,”将两堆隔开,依此类推。只需要判断扫描到的“,”的个数就知道经过了几次字符变换。 - 快速查找?
哈希表
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
int res = 1; //beginWord本身也在路径中
queue<string> q; //bfs问题基本少不了队列
unordered_map<string, int> mp;
//value默认为1,表示存在该词
for(int i = 0; i < wordList.size(); i++)
{
mp[wordList[i]] = 1;
}
if(mp.count(endWord) == 0)
{
return 0;
}
//队列每一层以“,”分隔
q.push(beginWord);
q.push(",");
while(!q.empty())
{
string temp = q.front();
q.pop();
if(temp != ",")
{
for(int i = 0; i < temp.size(); i++)
{
char c_temp = temp[i];
for(char c = 'a'; c <= 'z'; c++)
{
if(c == c_temp)
{
continue;
}
temp[i] = c;
if(mp[temp] != 0)
{
//单词表中存在该单词,将单词加到队列中,同时从单词表中删去该单词
q.push(temp);
mp[temp] = 0;
//如果当前词和endWord相同,输出
if(temp == endWord)
{
return res + 1;
}
}
temp[i] = c_temp;
}
}
}
else if(!q.empty())
{
q.push(",");
res++;
}
}
return 0;
}