算法刷题--广度优先搜索 / 深度优先搜索

Code 1 : Flood Fill

An image is represented by an m x n integer grid image where image[i][j] represents the pixel value of the image.

You are also given three integers sr, sc, and newColor. You should perform a flood fill on the image starting from the pixel image[sr][sc].

To perform a flood fill, consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color), and so on. Replace the color of all of the aforementioned pixels with newColor.

Return the modified image after performing the flood fill.

Example 1

Input: image = [[1,1,1],[1,1,0],[1,0,1]], sr = 1, sc = 1, newColor = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
Explanation: From the center of the image with position (sr, sc) = (1, 1) (i.e., the red pixel), all pixels connected by a path of the same color as the starting pixel (i.e., the blue pixels) are colored with the new color.
Note the bottom corner is not colored 2, because it is not 4-directionally connected to the starting pixel.

Example 2

Input: image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, newColor = 2
Output: [[2,2,2],[2,2,2]]

Solution

广度优先探索

class Solution {
    
    

public:
	const int dx[4]={
    
    1,0,0,-1};
	const int dy[4]={
    
    0,1,-1,0};
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
    
    
    	int cur=image[sr][sc];
    	if(cur==newColor) return image;
    	int n=image.size();
    	int m=image[0].size();
    	queue<pair<int,int>> que;
    	que.emplace(sr,sc);
    	image[sr][sc]=newColor;
    	while(!que.empty()){
    
    
    		int a=que.front().first;
    		int b=que.front().second;
    		que.pop();
    		for (int i=0;i<4;i++){
    
    
    			int tx=a+dx[i];
    			int ty=b+dy[i];
               
    			if(tx>=0 && tx<n && ty>=0 && ty<m && (image[tx][ty]==cur)){
    
    
                    //cout<<tx<<' '<<ty<<endl;
    				que.emplace(tx,ty);
    				image[tx][ty]=newColor;
				}
			}
		}

		return image;
    }

};
  • 创建一个队列,每次把队列四周符合条件的点放在队列里。
  • 注意这里用到了可以储存两个数的队列queue<pair<int,int>> que,入队是emplace(),出队是pop

深度优先探索

class Solution {
    
    

public:
	
	const int dx[4]={
    
    -1,1,0,0};
	const int dy[4]={
    
    0,0,-1,1};
	void dfs(vector<vector<int>>&image,int x,int y,int color,int newColor){
    
    
		if(image[x][y]==color){
    
    
			image[x][y]==newColor;
			for(int i=0;i<4;i++){
    
    
				int tx=x+dx[i],ty=y+dy[i];
				if (tx>=0 && tx<image.size() && ty>=0 && ty<image[0].size()){
    
    
					dfs(image,tx,ty,color,newColor);
				}
			}
		}
	}
	vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
    
    
		int cur=image[sr][sc];
		if(cur!=newColor){
    
    
			dfs(image,sr,sc,cur,newColor);
		}
		return image;
    }
};

Code 2 : Max Aera OF Irland

You are given an m x n binary matrix grid. An island is a group of 1’s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.

The area of an island is the number of cells with a value 1 in the island.

Return the maximum area of an island in grid. If there is no island, return 0.

扫描二维码关注公众号,回复: 13329287 查看本文章

Example 1

Input: grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
Output: 6
Explanation: The answer is not 11, because the island must be connected 4-directionally.

Example 2

Input: grid = [[0,0,0,0,0,0,0,0]]
Output: 0

Solution

深度优先探索


class Solution {
    
    
	int dfs(vector<vector<int>>& grid,int x ,int y){
    
    
		 if (x < 0 || y < 0 ||x== grid.size() || y == grid[0].size() || grid[x][y] != 1) {
    
    
            return 0;
        }
		grid[x][y]=0;
		int dx[4]={
    
    0,0,1,-1};
		int dy[4]={
    
    1,-1,0,0};
		int ans=1;
		for(int i=0;i<4;i++){
    
    
			int xx=x+dx[i];
			int yy=y+dy[i];
		
			ans+=dfs(grid,xx,yy);
		}
		return ans;
	}
	public :
    int maxAreaOfIsland(vector<vector<int>>& grid) {
    
    
    	int ans=0;
    	for(int i=0;i<grid.size();i++){
    
    
    		for(int j=0;j<grid[0].size();j++){
    
    
    			ans=max(ans,dfs(grid,i,j));
			}
		}
		return ans;

    }
};

广度优先探索

class Solution{
    
    
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
    
    
    	int dx[4]={
    
    0,0,1,-1};
    	int dy[4]={
    
    -1,1,0,0};
    	int m=grid.size();
    	int n=grid[0].size();
    	int ans=0;  	
    	for(int r=0;r<m;r++){
    
    
			for(int c=0;c<n;c++){
    
    
				int count=0;
				queue<pair<int,int>> que; 			
   			 	que.emplace(r,c);
    			while(!que.empty()){
    
    
    					int x=que.front().first;
    					int y=que.front().second;
    					que.pop();
    					if(x<0 || y<0 || x==m || y==n || grid[x][y]!=1)
    						continue;
    					count++;
    					grid[x][y]=0;
						for(int i=0;i<4;i++){
    
    
    						int tx=x+dx[i];
    						int ty=y+dy[i];
    						que.emplace(tx,ty);
						}
					}
					ans=max(ans,count);
				}
			}
			return ans;
    }
};

这里的注意点 : 以前自己写的时候是先判断再入队,可能会造成计数上的混乱(第一个节点重复计数),应该先入队再判断。

Code 3 : Merge Two Binary Trees

You are given two binary trees root1 and root2.

Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of the new tree.

Return the merged tree.

Note: The merging process must start from the root nodes of both trees.

Example 1

Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
Output: [3,4,5,5,4,null,7]

Example 2

Input: root1 = [1], root2 = [1,2]
Output: [2,2]

Solution

深度优先探索

 * Definition for a binary tree node.
 * struct TreeNode {
    
    
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {
    
    }
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {
    
    }
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {
    
    }
 * };
 */
class Solution {
    
    
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
    
    
    	if(!root1) return root2;
    	if(!root2) return root1;
    	root1->val+=root2->val;
		root1->left=mergeTrees( root1->left, root2->left);
		root1->right=mergeTrees(root1->right,root2->right);
        return root1;
    }
};

广度优先探索

class Solution {
    
    
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
    
    
    	if(!root1) return root2;
    	if(!root2) return root1;
    	queue<TreeNode*> que1;
    	queue<TreeNode*> que2;
    	queue<TreeNode*> mq;
    	auto merged=new TreeNode(root1->val+root2->val);
        que1.push(root1);
        que2.push(root2);
    	mq.push(merged);
    	while(!que1.empty()&&!que2.empty()){
    
    
    		auto p1=que1.front();
			auto p2=que2.front();
			auto p=mq.front();
			que1.pop();
			que2.pop();
			mq.pop();
    		if(p1->left || p2->left){
    
    
    			if(p1->left && p2->left){
    
    
    				p->left=new TreeNode(p1->left->val+p2->left->val);
    				mq.push(p->left);
    				que1.push(p1->left);
    				que2.push(p2->left);
				}
				else if(p1->left){
    
    
					p->left=p1->left;
				}
				else{
    
    
					p->left=p2->left;
				}
			}
			if(p1->right || p2->right){
    
    
    			if(p1->right && p2->right){
    
    
    				p->right=new TreeNode(p1->right->val+p2->right->val);
    				mq.push(p->right);
    				que1.push(p1->right);
    				que2.push(p2->right);
				}
				else if(p1->right){
    
    
					p->right=p1->right;
				}
				else{
    
    
					p->right=p2->right;
				}
			}
		}
    	return merged;
    }
};

使用了三个队列,个人认为过于复杂,不是很好。

Code 4 : Populating Next Righ Pointers in Each Node

You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:

struct Node {
    
    
  int val;
  Node *left;
  Node *right;
  Node *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Example 1

Input: root = [1,2,3,4,5,6,7]
Output: [1,#,2,3,#,4,5,6,7,#]
Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.

Example 2

Input: root = []
Output: []

Solution

层序遍历

class Solution {
    
    
public:
    Node* connect(Node* root) {
    
    
    	if(!root) return root;
        queue<Node*> que;
        que.push(root);
        while(!que.empty()){
    
    
        	int size=que.size();
        	auto n=que.front();
        	Node* preNode;
        	Node* nextNode;
        	for(int i=0;i<size;i++){
    
    
        		if(i==0){
    
    
        			preNode=que.front();
        			nextNode=que.front();
        			que.pop();
				}
        		else{
    
    
        			nextNode=que.front();
        			preNode->next=nextNode;
        			que.pop();
        			preNode=preNode->next;
				}
				if(preNode->left) que.push(preNode->left);
				if(preNode->right) que.push(preNode->right);
    		}
    		preNode->next=NULL;
		}
		return root;
    }
};

理解记忆层序遍历相关模板,本题其实就多了preNodenextNode需要再循环体内多思考一下。同时要记得每一层最后一个要指向NULL。
以下是层序遍历模板

class Solution {
    
    
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        queue<TreeNode*> que;
        if(!root) que.push(root);
        vector<vector<int>>result;
        while(!que.empty()){
    
    
        	int size=que.size();
        	vector<int>vec;
        	for(int i=0;i<size;i++){
    
    
        		TreeNode* node=que.front();
        		que.pop();
        		vec.push_back(node->val);
        		if(node->left) que.push(node->left);
        		if(node->right) que.push(node->right);
			}
			result.push_back(vec);
		}
		return restlt;
    }
};

while循环中用for来循环每一层
利用已经建立好的next指针

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
    
    
public:
    Node* connect(Node* root) {
    
    
        if (!root) return root;
    	Node* leftmost=root;
    	while(leftmost->left){
    
    
    		Node* node=leftmost;
    		while(node){
    
    
    			node->left->next=node->right;
    			if(node->next) node->right->next=node->next->left;
    			node=node->next;
			}
			leftmost=leftmost->left;
		}
		return root;
    	
    }
};

每次在上一层规划好下一层的next指针。

Code 5 : 01Matrix

Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

Example 1

Input: mat = [[0,0,0],[0,1,0],[0,0,0]]
Output: [[0,0,0],[0,1,0],[0,0,0]]

Example 2:

Input: mat = [[0,0,0],[0,1,0],[1,1,1]]
Output: [[0,0,0],[0,1,0],[1,2,1]]

Solution

广度优先探索

class Solution {
    
    
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
    
    
		int n=mat.size();
		int m=mat[0].size();
		int dx[4]={
    
    0,0,1,-1};
		int dy[4]={
    
    1,-1,0,0};
		queue<pair<int,int>> que;
		
		for(int i=0;i<n;i++){
    
    
			for(int j=0;j<m;j++){
    
    
				if (mat[i][j]==0){
    
    
					que.emplace(i,j);
				}
				else mat[i][j]=-1;
			}
		}
		
		while(!que.empty()){
    
    
			int x=que.front().first;
			int y=que.front().second;
			que.pop();
			for(int i=0;i<4;i++){
    
    
				int tx=x+dx[i];
				int ty=y+dy[i];
				if(tx>=0&&tx<n&&ty>=0&&ty<m&&mat[tx][ty]==-1){
    
    
					mat[tx][ty]=mat[x][y]+1;
					que.emplace(tx,ty);
				}
			}
		}
		return mat;
    }
};

首先所有0 入队,然后从每一个0开始一圈一圈的向 1 扩散(每个 1 都是被离它最近的 0 扩散到的 )。这样就方便计算距离(直接是扩散起始点+1)。开始的时候将1都设置为-1也是为了方便判断是否被访问过(如果是1的话可能出现与距离1混淆的情况)。

Code 6 : Rotting Oranges

You are given an m x n grid where each cell can have one of three values:

0 representing an empty cell,
1 representing a fresh orange, or
2 representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.

Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1.

Example 1

Input: grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4

Example 2

Input: grid = [[2,1,1],[0,1,1],[1,0,1]]
Output: -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.

Example 3

Input: grid = [[0,2]]
Output: 0
Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.

Solution

广度优先探索

class Solution {
    
    
public:
    int orangesRotting(vector<vector<int>>& grid) {
    
    
		queue<pair<int,int>>que;
		int n=grid.size();
		int m=grid[0].size();
		int fresh=0;
		int dx[4]={
    
    0,0,1,-1};
		int dy[4]={
    
    1,-1,0,0};
		int time=0;
		for(int i=0;i<n;i++){
    
    
			for(int j=0;j<m;j++){
    
    
				if(grid[i][j]==1)	fresh++;
				if(grid[i][j]==2)	que.emplace(i,j);	
			}
		}
		while(!que.empty()){
    
    
			bool flag=false;
			int size=que.size();
			for(int i=0;i<size;i++){
    
    
				int x=que.front().first;
				int y=que.front().second;
				que.pop();
				for(int j=0;j<4;j++){
    
    
					int tx=x+dx[j];
					int ty=y+dy[j];
					if(tx>=0&&tx<n&&ty>=0&&ty<m&&grid[tx][ty]==1){
    
    
						flag=true;
						que.emplace(tx,ty);
						grid[tx][ty]=2;
						fresh--;
					}
				}
			}
			if(flag) time++;
		}
    if (fresh==0) return time;
    else return -1;	
    }
};
  • 让坏掉的橘子入队。每次while循环相当于是一分钟,检查坏掉的橘子周围有没有橘子会坏并且让他们入队。
  • 需要在起始记录新鲜的总个数,每坏一个减少一个,因为存在可能坏不了的情况。
  • 注意一个细节:要用一个flag判断这一轮是否有橘子坏掉,因为可能最后一轮是没有橘子坏掉的。

猜你喜欢

转载自blog.csdn.net/yxyxxxyyyy/article/details/120208460