思路:有向图中节点的入度和出度的概念。在有向图中,一个节点的入度是指向该节点的边的数量;而一个节点的出度是从该节点出发的边的数量。
题干描述了一个有向图。每个人是图的节点,统计每个节点的入度和出度。
根据题意,在法官存在的情况下,法官不相信任何人,每个人(除了法官外)都信任法官,且只有一名法官。因此法官这个节点的入度是 n-1, 出度是 0。
我们可以遍历每个节点的入度和出度,如果找到一个符合条件的节点,由于题目保证只有一个法官,我们可以直接返回结果;如果不存在符合条件的点,则返回 -1。
时间复杂度:O(m+n)
空间复杂度:O(n)
代码:
class Solution {
public:
int findJudge(int n, vector<vector<int>>& trust) {
vector<int> indegrees(n+1);
vector<int> outdegrees(n+1);
for(auto & edge:trust)
{
int x=edge[0];
int y=edge[1];
indegrees[y]++;
outdegrees[x]++;
}
for(int i=1;i<n+1;i++)
{
if(indegrees[i]==n-1&&outdegrees[i]==0)
return i;
}
return -1;
}
};
首先我们先找到值为1的点,将这点赋值为0,然后判断这个点的相邻的3个点是否为1,也就是若为1,将这3个点的赋值为0,然后再分别将这三个点的相邻的三个点判断,判断是否为1,若为1则将其值赋值为0.一直递归下去,直到遍历完整个二维数组。
时间复杂度:O(mn),m为行,n为列
空间复杂度:最坏情况下都为陆地则O(mn)。
class Solution {
public:
void dfs(vector<vector<char>>& grid,int row,int column){
int nrow=grid.size();
int ncolumn=grid[0].size();
grid[row][column]='0';
if(row-1>=0&&grid[row-1][column]=='1') dfs(grid,row-1,column);
if(row+1<=nrow-1&&grid[row+1][column]=='1')
dfs(grid,row+1,column);
if(column-1>=0&&grid[row][column-1]=='1')
dfs(grid,row,column-1);
if(column+1<=ncolumn-1&&grid[row][column+1]=='1')
dfs(grid,row,column+1);
}
int numIslands(vector<vector<char>>& grid) {
int nr=grid.size();
if(nr==0)
return 0;
int nc=grid[0].size();
int num_island=0;
for(int i=0;i<nr;i++)
for(int j=0;j<nc;j++)
{
if(grid[i][j]=='1')
{
num_island++;
dfs(grid,i,j);
}
}
return num_island;
}
};
解题思路:
当有n个节点时,找到中心节点,哪么除了中心节点以外,其余的节点都连接到中心节点上,所以中心节点的度为n-1。
代码:
class Solution {
public:
int findCenter(vector<vector<int>>& edges) {
int n=edges.size()+1;
vector<int> indegrees(n+1);
for(auto &depart : edges){
int x=depart[0];
int y=depart[1];
indegrees[x]++;
indegrees[y]++;
}
for(int i=1;i<=n;i++)
{
if(indegrees[i]==n-1)
return i;
}
return -1;
}
};
使用深度优先遍历搜索,当(nr,nc)节点颜色是所需要涂漆的颜色时,就不用折腾了,直接返回该图。当(nr,nc)节点颜色不是是所需要涂漆的颜色时,我们要找到与该节点颜色相同的临近节点,并将满足条件的临近节点涂漆为newcolor。如何找到与该节点颜色相同的临近节点呢?使用递归方法,分别对该节点的上、下、左、右四个方向的节点进行判断,然后再分别对这四个节点的上下左右四个节点进行判断,一直递归,递归结束的条件是与他们邻近的节点中找不到与初始颜色相同的节点。
代码:
class Solution {
public:
void dfs(vector<vector<int>>& image, int sr, int sc, int newcolor,int color){
int nrow=image.size();
int ncolumn=image[0].size();
if(image[sr][sc]==color){
image[sr][sc]=newcolor;
if(sr-1>=0)
dfs(image,sr-1,sc,newcolor,color);
if(sr+1<=nrow-1)
dfs(image,sr+1,sc,newcolor,color);
if(sc-1>=0)
dfs(image,sr,sc-1,newcolor,color);
if(sc+1<=ncolumn-1)
dfs(image,sr,sc+1,newcolor,color);
}
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
int beforeColor=image[sr][sc];
if(beforeColor==color)
return image;
else
dfs(image,sr,sc,color,beforeColor);
return image;
}
};
思路:dfs函数用于返回岛屿的陆地的面积,每找到一个岛屿后,将这个岛屿的面积进行返回。然后找到岛屿的最大值进行返回。
dfs函数递归的终止条件为:当传递的行坐标或列坐标不在整个区域内,返回0。当传递的点的值为0时,返回0。否则返回ans,ans是岛屿的面积。
具体实现的过程:首先在整个区域中找到值为1的点,将这点赋值为0,初始ans值为1.然后判断这个点的相邻的4个点是否为1,若其中有的点值为1,将这点的赋值为0,。然后再分别将这4个点的相邻的4个点判断,判断是否为1,若为1则将其值赋值为0,ans+dfs().一直递归下去,直到遍历完整个二维数组。
代码:
class Solution {
public:
int dfs(vector<vector<int>> &grid,int row,int column){
int nrow=grid.size();
int ncolumn=grid[0].size();
if(row<0||column<0||row>=nrow||column>=ncolumn||grid[row][column]==0)
return 0;
int ans=1;
grid[row][column]=0;
if(row-1>=0)
ans+=dfs(grid,row-1,column);
if(row+1<=nrow-1)
ans+=dfs(grid,row+1,column);
if(column>=0)
ans+=dfs(grid,row,column-1);
if(column+1<=ncolumn-1)
ans+=dfs(grid,row,column+1);
return ans;
}
int maxAreaOfIsland(vector<vector<int>>& grid) {
int res=0;
for(int i=0;i<grid.size();i++)
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]==1)
res=max(res,dfs(grid,i,j));
}
return res;
}
};
解题思路:
本题要求找到不靠边的陆地面积,那么我们只要从周边找到陆地然后 通过 dfs或者bfs 将周边靠陆地且相邻的陆地都变成海洋,然后再去重新遍历地图的时候,统计此时还剩下的陆地就可以了。
代码:
class Solution {
public:
void dfs(vector<vector<int>>& grid,int row,int column){
int nrow=grid.size();
int ncolumn=grid[0].size();
if(row<0||column<0||row>=nrow||column>=ncolumn||grid[row][column]==0)
return;
grid[row][column]=0;
if(row-1>=0)
dfs(grid,row-1,column);
if(row+1<=nrow-1)
dfs(grid,row+1,column);
if(column-1>=0)
dfs(grid,row,column-1);
if(column+1<=ncolumn-1)
dfs(grid,row,column+1);
}
int numEnclaves(vector<vector<int>>& grid) {
int nrow=grid.size();
int ncolumn=grid[0].size();
for(int i=0;i<nrow;i++){
if(grid[i][0]==1)
dfs(grid,i,0);
if(grid[i][ncolumn-1]==1)
dfs(grid,i,ncolumn-1);
}
for(int j=0;j<ncolumn;j++){
if(grid[0][j]==1)
dfs(grid,0,j);
if(grid[nrow-1][j]==1)
dfs(grid,nrow-1,j);
}
int num=0;
for(int i=0;i<nrow;i++)
for(int j=0;j<ncolumn;j++)
if(grid[i][j]==1)
num++;
return num;
}
};
解题思路:
1.若某一个点在grid1中是水域,在grid2中是陆地,则在grid2中将这一点及其附近的陆地用水淹没。
2.计算grid2中剩余的岛屿数量。
代码:
class Solution {
public:
void dfs(vector<vector<int>>& grid,int row,int column){
int nrow=grid.size();
int ncolumn=grid[0].size();
if(row<0||column<0||row>=nrow||column>=ncolumn||grid[row][column]==0)
return;
grid[row][column]=0;
dfs(grid,row-1,column);
dfs(grid,row+1,column);
dfs(grid,row,column-1);
dfs(grid,row,column+1);
}
int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
int nrow=grid1.size();
int ncolumn=grid1[0].size();
int nums=0;
for(int i=0;i<nrow;i++)
for(int j=0;j<ncolumn;j++)
{
if(grid1[i][j]==0&&grid2[i][j]==1)
dfs(grid2,i,j);
}
for(int i=0;i<nrow;i++)
for(int j=0;j<ncolumn;j++){
if(grid2[i][j]==1)
{nums++;
dfs(grid2,i,j);
}
}
return nums;
}
};
解题思路:
使用dijstra来求单源最短路径,即求出给定的点k到每一点的距离的最小值,在这些最小值中最大的值即为所求值。
代码:
class Solution {
public:
int networkDelayTime(vector<vector<int>> ×, int n, int k) {
const int inf = INT_MAX / 2;
vector<vector<int>> g(n, vector<int>(n, inf));
for (auto &t : times) {
int x = t[0] - 1, y = t[1] - 1;
g[x][y] = t[2];
}
vector<int> dist(n, inf);
dist[k - 1] = 0;
vector<int> used(n);
for (int i = 0; i < n; ++i) {
int x = -1;
for (int y = 0; y < n; ++y) {
if (!used[y] && (x == -1 || dist[y] < dist[x])) {
x = y;
}
}
used[x] = true;
for (int y = 0; y < n; ++y) {
dist[y] = min(dist[y], dist[x] + g[x][y]);
}
}
int ans = *max_element(dist.begin(), dist.end());
return ans == inf ? -1 : ans;
}
};
解题思路为:
题目的二维矩阵可以看做是通过邻接矩阵来存储图,通过计算图的连通分量即为省份的数量。
深度优先搜索的思路是很直观的。遍历所有城市,对于每个城市,如果该城市尚未被访问过,则从该城市开始深度优先搜索,通过矩阵 isConnected 得到与该城市直接相连的城市有哪些,这些城市和该城市属于同一个连通分量,然后对这些城市继续深度优先搜索,直到同一个连通分量的所有城市都被访问到,即可得到一个省份。遍历完全部城市以后,即可得到连通分量的总数,即省份的总数。
代码:
class Solution {
public:
void dfs(vector<vector<int>>& isConnected,vector<int> &visited,int cities,int i){
for(int j=0;j<cities;j++)
{
if(isConnected[i][j]==1&&!visited[j])
{
visited[j]=1;
dfs(isConnected,visited,cities,j);
}
}
}
int findCircleNum(vector<vector<int>>& isConnected) {
int cities=isConnected.size();
vector<int> visited(cities);
int provinces=0;
for(int i=0;i<cities;i++){
if(!visited[i]){
dfs(isConnected,visited,cities,i);
provinces++;
}
}
return provinces;
}
};