目录
一、盒子与扑克牌
二、员工的重要性
三、图像渲染
一、盒子与扑克牌
假如有编号为1~3的3张扑克牌和编号为1~3的3个盒子,现在需要将3张牌分别放到3个盒子中去,且每个盒子只能放
一张牌,一共有多少种不同的放法。
当走到一个盒子面前的时候,到底要放那一张牌呢?在这里应该把所有的牌都尝试一遍。假设这里约定一个顺
序,按牌面值从小到大依次尝试。在这样的假定下,当走到第一个盒子的时候,放入1号牌。
放好之后,继续向后走,走到第二个盒子面前,此时还剩2张牌,牌面值最小的为2号牌,按照约定的规则,把2
号牌放入第二个盒子。
此时,来到第三个盒子面前,只剩一张牌,放入第三个盒子。此时手中的牌已经用完。
继续向后走,走到了盒子的尽头,后面再也没有盒子,并且也没有可用的牌了,此时,一种放法已经完成了,
但是这只是一种放法,这条路已经走到了尽头,还需要折返,重新回到上一个盒子。
这里回到第三个盒子,把第三个盒子中的牌取出来,再去尝试能否再放其它的牌,这时候手里仍然只有一张3号
牌,没有别的选择了,所以还需要继续向后回退,回到2号盒子面前。
收回2号盒子中的2号牌,现在手里有两张牌,2,3,按照约定,再把3号牌放入2号盒子,放好之后,继续向后
走,来到3号盒子。
此事手里只有一张2号牌,把它放入3号盒子,继续向后走。
此时这条路又一次走到了尽头,一个新的放法又产生了,继续向上折返,尝试其它可能,按照上述步骤,依次
会产生所有结果。
代码如何实现这种过程呢?最主要的事情,向面前的盒子里放每一种牌,一个for循环搞定。这里还需考虑,现在手里有没有这张牌,用一个数组book标记手里是否有这张牌
void DFS(vector<int>& book, vector<int>& box, int idx, int n)
{
// 遍历到最后一个元素返回
if (idx == n+1)
{
for (int i = 1; i <= n; i++)
cout << box[i] << " ";
cout << endl;
return;
}
for (int i = 1; i <= n; i++)
{
if (book[i] == 0)
{
box[idx] = i;//第idx盒子放第i张牌
book[i] = 1;
// 处理下一个
DFS(book, box, idx + 1, n);
// 回收
book[i] = 0;
}
}
}
void test1()
{
int n;
cin >> n;
vector<int> book(n + 1, 0);
vector<int> box(n + 1, 0);
DFS(book, box, 1, n);
}
二、员工的重要性
690. 员工的重要性https://leetcode.cn/problems/employee-importance/
给定一个保存员工信息的数据结构,它包含了员工 唯一的 id ,重要度 和 直系下属的 id 。
比如,员工 1 是员工 2 的领导,员工 2 是员工 3 的领导。他们相应的重要度为 15 , 10 , 5 。那么员工 1 的数据结构是 [1, 15, [2]] ,员工 2的 数据结构是 [2, 10, [3]] ,员工 3 的数据结构是 [3, 5, []] 。注意虽然员工 3 也是员工 1 的一个下属,但是由于 并不是直系 下属,因此没有体现在员工 1 的数据结构中。
现在输入一个公司的所有员工信息,以及单个员工 id ,返回这个员工和他所有下属的重要度之和。
首先将所有员工id与员工结点存入哈希表中
从给出的id作为根节点开始进行结点值importance的计算
遍历每一个员工id对应的下属id,继续dfs其下属id以下部分的importance
/*
// Definition for Employee.
class Employee {
public:
int id;
int importance;
vector<int> subordinates;
};
*/
class Solution {
public:
map<int, Employee*> mp;
int dfs(int id)
{
int num = mp[id]->importance;
for(auto e : mp[id]->subordinates) // 遍历该id对应的下属id
{
num += dfs(e);
}
return num;
}
int getImportance(vector<Employee*> employees, int id) {
// 用哈希表来保存每个id对应的员工
for(auto e : employees)
mp[e->id] = e;
return dfs(id);
}
};
三、图像渲染
733. 图像渲染https://leetcode.cn/problems/flood-fill/
有一幅以 m x n 的二维整数数组表示的图画 image ,其中 image[i][j] 表示该图画的像素值大小。
你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。
为了完成 上色工作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。
最后返回 经过上色渲染后的图像 。
总的来说就是从给出起点开始,把与它相接的图块都染成和它一样的颜色。
总体DFS思路就是从起点开始染色,然后上下左右移动,移动完之后判断是否越界,如果不越界并且新位置没有被走过并且颜色需要被涂改就DFS该位置。(注意这个方向矩阵的引入,一般情况下我都会写出四次判断来进行哈哈哈哈)
从圈圈开始,涂改所有颜色为绿色的块
int nextP[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
class Solution {
public:
void DFS(vector<vector<int>>& image, int row, int col, vector<vector<bool>>& book,
int curX, int curY, int oldcolor, int newcolor)
{
// 先进行渲染当前颜色
image[curX][curY] = newcolor;
book[curX][curY] = true;
// 判断上下左右位置是否需要渲染
for(int i = 0; i < 4; i++)
{
int newX = curX + nextP[i][0];
int newY = curY + nextP[i][1];
// 判断下一个位置是否越界
if(newX>=row||newX<0||newY>=col||newY<0)
continue;
if(book[newX][newY]==false && image[newX][newY]==oldcolor)
DFS(image, row, col, book, newX, newY, oldcolor, newcolor);
}
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
if(image.empty())
return image;
int row = image.size();
int col = image[0].size();
vector<vector<bool>> book(row, vector<bool> (col, false));
int oldcolor = image[sr][sc];
DFS(image, row, col, book, sr, sc, oldcolor, color);
return image;
}
};