1.二叉树的层次遍历
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
返回其层次遍历结果:
[ [3], [9,20], [15,7] ]
实现
判断根节点是否为NULL,如果是,直接返回空。
将根节点插入到队列中,遍历整个队列。
队列的顶部元素出队,存储其值。
判断左右节点是否为空,如果不为空,则将其入队。
重复步骤3.
注意:需要记得队列中现目前的元素数量。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode* >q;
if(root==NULL)
return res;
q.push(root);
while(!q.empty())
{
vector<int> ans;
int size=q.size();
for(int i=0;i<size;i++)
{
auto p=q.front();
q.pop();
ans.push_back(p->val);
if(p->left!=NULL)
{
q.push(p->left);
}
if(p->right!=NULL)
{
q.push(p->right);
}
}
res.push_back(ans);
ans.clear();
}
return res;
}
};
2.腐烂的橘子(leetcode 994)
在给定的网格中,每个单元格可以有以下三个值之一:
- 值
0
代表空单元格; - 值
1
代表新鲜橘子; - 值
2
代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1
。
示例 1:
输入:[[2,1,1],[1,1,0],[0,1,1]] 输出:4
示例 2:
输入:[[2,1,1],[0,1,1],[1,0,1]] 输出:-1 解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:
输入:[[0,2]] 输出:0 解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
提示:
1 <= grid.length <= 10
1 <= grid[0].length <= 10
grid[i][j]
仅为0
、1
或2
实现
- 找出初始腐烂橘子的位置,插入到队列中。
- 判断队列是否为空,如果不为空,队列的顶部元素出队,对上、下、左、右四个方向的橘子进行腐烂操作,腐烂的橘子置为2。注意:需要在边界处判断是否越界。
- 新的腐烂橘子插入到队列中,重复2。
- 然后再次遍历整个区域,判断是否把所有的橘子都腐烂了。
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
int rows=grid.size();
int cols=grid[0].size();
std::queue<std::pair<int,int>> orange;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(grid[i][j]==2)
orange.push({i,j});
}
}
int time=0;
while (!orange.empty())
{
int size=orange.size();
bool flag= false;
for(int i=0;i<size;i++)
{
std::pair<int,int> temp=orange.front();
int row=temp.first;
int col=temp.second;
orange.pop();
if(col+1<cols&&grid[row][col+1]==1)
{
flag= true;
grid[row][col+1]=2;
orange.push({row,col+1});
}
if(col-1>=0&&grid[row][col-1]==1)
{
flag= true;
grid[row][col-1]=2;
orange.push({row,col-1});
}
if(row+1<rows&&grid[row+1][col]==1)
{
flag= true;
grid[row+1][col]=2;
orange.push({row+1,col});
}
if(row-1>=0&&grid[row-1][col]==1)
{
flag= true;
grid[row-1][col]=2;
orange.push({row-1,col});
}
}
if(flag)
time++;
}
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(grid[i][j]==1)
return -1;
}
}
return time;
}
};
3.水壶问题(leetcode 365)
-
日期:2020/3/21
有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
- 装满任意一个水壶
- 清空任意一个水壶
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例 1: (From the famous "Die Hard" example)
输入: x = 3, y = 5, z = 4 输出: True
示例 2:
输入: x = 2, y = 6, z = 5 输出: False
- 补充学习知识:std::unordered_set自定义函数
参考:STL: unordered_map 自定义键值类型的使用(C++)
以 x = 1, y = 3, z = 2 为例,一共有八种状态:(0,0), (1,0),(0,1), (1,1),(0,2), (1,2),(0,3), (1,3)。可以以这八种状态构建如下的图:
- 节点表示两个水壶的状态
- 边表示操作方法:分别为倒满A/B,倒空A/B,A倒入B,B倒入A 六种方法。
- 这是一个有向图,因为有些状态并不能护互为转移。比如 (1,1) 和 (1,0)。
广度优先搜索(BFS):该过程总是从一个或若干个起始点开始,沿着边像水波一样逐层向外遍历,直到所有的点已被访问或者到达目标状态。
实现
1.初始时,队列和set均为空。将起始点放入队列及set。
2.如果队列为空则 bfs 结束。
3.弹出队首元素并访问其周围元素,设为 p。
4.如果p为目标状态则 bfs 结束。
5. p 执行6种操作,将不在set中的元素放入队列及set。跳转第 2 步。
class Solution {
public:
pair<int,int> op(int type,pair<int,int> &state,int x,int y)
{
switch(type)
{
case 0:
return make_pair(x,state.second);
case 1:
return make_pair(state.first,y);
case 2:
return make_pair(0,state.second);
case 3:
return make_pair(state.first,0);
case 4:
{
int move = min(state.first, y-state.second);
return make_pair(state.first - move, state.second + move);
}
case 5:
{
int move = min(x-state.first, state.second);
return make_pair(state.first + move, state.second - move);
}
}
return make_pair(0,0);
}
struct HashPair {
size_t operator()(const pair<int, int> &key) const noexcept
{
return size_t(key.first)*100000007 + key.second;
}
};
bool canMeasureWater(int x, int y, int z) {
unordered_set<pair<int,int>,HashPair> s;
queue<pair<int,int>> q;
q.push({0,0});
while(!q.empty())
{
auto p=q.front();
q.pop();
if(p.first+p.second==z)
return true;
for(int i=0;i<6;i++)
{
auto points=op(i,p,x,y);
if(s.find(points)!=s.end())
continue;
s.insert(points);
q.push(points);
}
}
return false;
}
};