算法:BFS宽度优先遍历

文章目录

  • BFS与Queue相结合
    • N叉树的层序遍历
    • 二叉树的锯齿形层序遍历
    • 二叉树的最大宽度
  • BFS和FLoodFill相结合
    • 图像渲染
    • 岛屿数量
    • 岛屿的最大面积
  • BFS解决最短路问题
    • 最小基因变化
    • 单词接龙
    • 为高尔夫比赛砍树

本篇总结的是BFS算法,BFS算法相比起DFS算法来说还是比较简单的

BFS与Queue相结合

N叉树的层序遍历

在这里插入图片描述

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution 
{
public:
    vector<vector<int>> levelOrder(Node* root) 
    {
        vector<vector<int>> ret;
        if(root == nullptr)
            return ret;
        queue<Node*> qe;
        qe.push(root);
        while(!qe.empty())
        {
            int size = qe.size();
            vector<int> tmp;
            for(int i = 0; i < size; i++)
            {
                // 取队列头节点
                Node* front = qe.front();
                qe.pop();
                // 把值入到数组中
                tmp.push_back(front->val);
                // 如果有孩子,就把孩子入到队列中
                for(int j = 0; j < (front->children).size(); j++)
                    qe.push((front->children)[j]);
            }
            ret.push_back(tmp);
        }
        return ret;
    }
};

二叉树的锯齿形层序遍历

在这里插入图片描述
这里提供一种双端队列的做法,也可以在合适的层数逆序

/**
 * 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:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) 
    {
        vector<vector<int>> res;
        if(root == nullptr)
            return res;
        bool status = true;
        queue<TreeNode*> qe;
        qe.push(root);
        while(!qe.empty())
        {
            int size = qe.size();
            deque<int> v;
            for(int i = 0; i < size; i++)
            {
                TreeNode* front = qe.front();
                qe.pop();
                if(status)
                    v.push_back(front->val);
                else
                    v.push_front(front->val);
                if(front->left) 
                    qe.push(front->left);
                if(front->right) 
                    qe.push(front->right);
            }
            res.push_back(vector<int>(v.begin(), v.end()));
            status = !status;
        }
        return res;
    }
};

二叉树的最大宽度

在这里插入图片描述

/**
 * 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:
    int widthOfBinaryTree(TreeNode* root) 
    {
        // 用数组来模拟队列,有助于最后计算,这里没用
        queue<pair<TreeNode*, unsigned int>> v;
        v.push(make_pair(root, 1));
        unsigned int lenth = 0;
        while(!v.empty())
        {
            // 计算一下这中间长度的差
            lenth = max(lenth, v.back().second - v.front().second + 1);
            int size = v.size();
            for(int i = 0; i < size; i++)
            {
                // 取头
                auto front = v.front();
                v.pop();
                // 如果有左或者有右节点,就进去
                if(front.first->left) 
                    v.push(make_pair(front.first->left, (front.second) * 2));
                if(front.first->right) 
                    v.push(make_pair(front.first->right, (front.second) * 2 + 1));
            }
        }
        return lenth;
    }
};

BFS和FLoodFill相结合

图像渲染

在这里插入图片描述

class Solution 
{
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) 
    {
        int oldcolor = image[sr][sc];
        int newcolor = color;
        if(oldcolor == newcolor)
            return image;
        queue<pair<int, int>> q;
        q.push({sr, sc});
        while(!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            image[a][b] = newcolor;
            for(int k = 0; k < 4; k++)
            {
                int x = dx[k] + a, y = dy[k] + b;
                if(x >= 0 && x < image.size() && y >=0 && y < image[0].size() && image[x][y] == oldcolor)
                    q.push({x, y});
            }
        }
        return image;
    }
};

岛屿数量

在这里插入图片描述

class Solution
{
    int res = 0;
    int dx[4] = { 1, -1, 0, 0 };
    int dy[4] = { 0, 0, 1, -1 };
public:
    int numIslands(vector<vector<char>>& grid)
    {
        vector<vector<bool>> check;
        check.resize(grid.size(), vector<bool>(grid[0].size(), false));
        queue<pair<int, int>> q;
        for (int i = 0; i < grid.size(); i++)
        {
            for (int j = 0; j < grid[0].size(); j++)
            {
                if (grid[i][j] == '1' && check[i][j] == false)
                {
                    check[i][j] = true;
                    q.push({ i, j });
                    while (!q.empty())
                    {
                        auto [a, b] = q.front();
                        q.pop();
                        for (int k = 0; k < 4; k++)
                        {
                            int x = dx[k] + a, y = dy[k] + b;
                            if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size() && grid[x][y] == '1' && check[x][y] == false)
                            {
                                check[x][y] = true;
                                q.push({ x, y });
                            }
                        }
                    }
                    res++;
                }
            }
        }
        return res;
    }
};

岛屿的最大面积

在这里插入图片描述

class Solution 
{
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        int res = 0, maxsize = 0, dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
        vector<vector<bool>> check(grid.size(), vector<bool>(grid[0].size(), false));
        queue<pair<int, int>> q;
        for(int i = 0; i < grid.size(); i++)
        {
            for(int j = 0; j < grid[0].size(); j++)
            {
                if(check[i][j] == false && grid[i][j] == 1)
                {
                    check[i][j] = true;
                    q.push({i, j});
                    res++;
                    while(!q.empty())
                    {
                        auto [a, b] = q.front();
                        q.pop();
                        for(int k = 0; k < 4; k++)
                        {
                            int x = dx[k] + a, y = dy[k] + b;
                            if(x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size() && grid[x][y] == 1 && check[x][y] == false)
                            {
                                check[x][y] = true;
                                q.push({x, y});
                                res++;
                            }
                        }
                    }
                    maxsize = max(res, maxsize);
                    res = 0;
                }
            }
        }
        return maxsize;
    }
};

BFS解决最短路问题

最小基因变化

在这里插入图片描述

class Solution
{
public:
	int minMutation(string startGene, string endGene, vector<string>& bank)
	{
		// 首先把符合要求的字符串丢到哈希表中
		unordered_map<string, int> hash;
		for (auto& str : bank)
			hash[str]++;
		// vis数组用来存储已经加过的状态
		unordered_map<string, int> visited;

		char arr[4] = { 'A', 'C', 'G', 'T' };
		int step = 0;
		queue<string> q;
		q.push(startGene);
		visited[startGene]++;
		while (!q.empty())
		{
			step++;
			int qsize = q.size();
			for (int k = 0; k < qsize; k++)
			{
				string front = q.front();
				q.pop();
				// 对于字符串中的每一个元素都要进行枚举
				for (int i = 0; i < front.size(); i++)
				{
					string tmp = front;
					// front中的每一个元素都要被枚举四次
					for (int j = 0; j < 4; j++)
					{
						tmp[i] = arr[j];
						// 如果front在visited中存在,说明这个元素已经被找过了
						if (visited.count(tmp) == 0)
						{
							// 如果这个元素还在bank中,那么就是有效状态,那么就可以进入队列中
							if (hash.count(tmp))
							{
								q.push(tmp);
								visited[tmp]++;
								if (tmp == endGene)
									return step;
							}
						}
					}
				}
			}
		}
		return -1;
	}
};

单词接龙

在这里插入图片描述

class Solution 
{
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) 
    {
        // 用哈希表存储符合要求的顶点和已经访问过的顶点
        unordered_map<string, int> hash;
        unordered_map<string, int> visited;
        // 把wordlist中元素存储到哈希中
        for(auto& str : wordList)
            hash[str]++;
        // 把wordlist中的元素含有的字母进行标记
        set<int> st;
        for(auto str : wordList)
        {
            for(auto e : str)
            {
                st.insert(e);
            }
        }
        int stsize = st.size();
        // 定义一些变量
        int ret = 1;
        queue<string> q;
        q.push(beginWord);
        visited[beginWord]++;
        while(!q.empty())
        {
            int qsize = q.size();
            ret++;
            for(int i = 0; i < qsize; i++)
            {
                // 进入循环中一次,就意味着走了一步
                string front = q.front();
                q.pop();
                // 单词的每一个字母都可以进行变换
                for(int j = 0; j < front.size(); j++)
                {
                    string tmp = front;
                    // 每一个字母都有26种变换方式
                    for(int k = 0; k < 26; k++)
                    {
                        // 如果这个元素在set中出现过就可以使用
                        if(st.count('a' + k))
                            tmp[j] = 'a' + k;
                        else
                            continue;
                        // 对于变换后的结果tmp,如果这个结果在list中才能继续
                        if(hash.count(tmp) && visited.count(tmp) == 0)
                        {
                            // 如果tmp没有被访问过才能继续
                            visited[tmp]++;
                            q.push(tmp);
                            if(tmp == endWord)
                                return ret;
                        }
                    }
                }
            }
        }
        return 0;
    }
};

为高尔夫比赛砍树

在这里插入图片描述

struct Cmp
{
	bool operator()(const pair<int, pair<int, int>>& p1, const pair<int, pair<int, int>>& p2)
	{
		return p1.first > p2.first;
	}
};

class Solution
{
	int dx[4] = { 1, -1, 0, 0 };
	int dy[4] = { 0, 0, 1, -1 };
public:
	int cutOffTree(vector<vector<int>>& forest)
	{
		int m = forest.size(), n = forest[0].size();
		// 首先要把矩阵的信息存储起来
		priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, Cmp> heap;
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				if (forest[i][j] != 1 && forest[i][j] != 0)
					heap.push(make_pair(forest[i][j], make_pair(i, j)));
		// 此时堆中就是按高度排列,并且每一个高度会对应其下标
		int step = 0;
		int x = 0, y = 0;
		while (!heap.empty())
		{
			auto top = heap.top();
			heap.pop();
			int ans = bfs(x, y, top.second.first, top.second.second, forest);
			if (ans == -1)
				return -1;
			step += ans;
			x = top.second.first;
			y = top.second.second;
		}
		return step;
	}

	// bfs函数,用来寻找从[curx, cury]到[nextx, nexty]的最短路径
	int bfs(int curx, int cury, int nextx, int nexty, vector<vector<int>>& forest)
	{
		if (curx == nextx && cury == nexty)
			return 0;
		int m = forest.size(), n = forest[0].size();
		vector<vector<bool>> visited(m, vector<bool>(n, false));
		int step = 0;
		queue<pair<int, int>> q;
		q.push({ curx, cury });
		visited[curx][cury] = true;
		while (!q.empty())
		{
			int qsize = q.size();
			step++;
			for (int i = 0; i < qsize; i++)
			{
				auto [a, b] = q.front();
				q.pop();
				for (int k = 0; k < 4; k++)
				{
					int x = a + dx[k], y = b + dy[k];
					if (x == nextx && y == nexty)
						return step;
					// 如果这个下标合法,并且没有被选过,并且不是障碍,就进队列
					if (x >= 0 && x < m && y >= 0 && y < n && visited[x][y] == false && forest[x][y] != 0)
					{
						visited[x][y] = true;
						q.push({ x, y });
					}
				}
			}
		}
		return -1;
	}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/266835.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于 Sentry 的前端监控系统搭建(Linux)

一、前言 随着技术这几年的发展与沉淀&#xff0c;线上数据指标监控也变得尤为重要&#xff0c;研发人员和运营人员需要对线上的产品指标有所感知&#xff0c;同时风险也需要及时暴露&#xff0c;很多公司开始自建监控系统&#xff0c;但对于一些定制化要求不是特别高的团队&a…

Spark的核心概念:RDD、DataFrame和Dataset

Apache Spark&#xff0c;其核心概念包括RDD&#xff08;Resilient Distributed Dataset&#xff09;、DataFrame和Dataset。这些概念构成了Spark的基础&#xff0c;可以以不同的方式操作和处理数据&#xff0c;根据需求选择适当的抽象。 RDD&#xff08;Resilient Distribute…

Linux学习教程(第十七章 LAMP环境搭建和LNMP环境搭建)一

第十七章 LAMP环境搭建和LNMP环境搭建&#xff08;一&#xff09; LAMP 环境搭建指的是在 Linux 操作系统中分别安装 Apache 网页服务器、MySQL 数据库服务器和 PHP 开发服务器&#xff0c;以及一些对应的扩展软件。 LAMP 环境是当前极为流行的搭建动态网站的开源软件系统&…

【模式识别】探秘分类奥秘:最近邻算法解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《模式之谜 | 数据奇迹解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1f30c;1 初识模式识…

行为型设计模式(五):访问者模式 观察者模式

访问者模式 Visitor 1、什么是访问者模式 访问者模式允许定义一些不改变数据结构的前提下的操作。通过这种方式&#xff0c;可以在不修改元素类的情况下定义新的操作。访问者模式常用于对复杂对象结构进行操作&#xff0c;而又不希望在这些对象上破坏封装性。 2、为什么使用…

YOLOv8改进 | 主干篇 | 利用SENetV1改进网络结构 (ILSVRC冠军得主)

一、本文介绍 本文给大家带来的改进机制是SENet&#xff08;Squeeze-and-Excitation Networks&#xff09;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何一个模型相结合的模块(可以看作是一…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《计及风电不确定性的多场景多时段安全约束机组组合解耦求解方法》

这个标题涉及到一种解决在能源系统中考虑风电不确定性的方法。让我们逐步分解这个标题&#xff0c;以便更好地理解其含义&#xff1a; 计及风电不确定性&#xff1a; 这指的是在能源系统中&#xff0c;风力发电的产出具有不确定性。因为风速是难以预测的&#xff0c;风力发电的…

nodejs+vue+ElementUi大学新生入学系统的设计与实现1hme0

采用B/S模式架构系统&#xff0c;开发简单&#xff0c;只需要连接网络即可登录本系统&#xff0c;不需要安装任何客户端。开发工具采用VSCode&#xff0c;前端采用VueElementUI&#xff0c;后端采用Node.js&#xff0c;数据库采用MySQL。 涉及的技术栈 1&#xff09; 前台页面…

TokenFlow详解

https://github.com/omerbt/TokenFlow/issues/25 https://github.com/omerbt/TokenFlow/issues/31 https://github.com/omerbt/TokenFlow/issues/32 https://github.com/eps696/SDfu register_extended_attention_pnp1. 为所有BasicTransformerBlock layer的attn1重构forward2.…

LeetCode 剑指 Offer II 054. 所有大于等于节点的值之和

给定一个二叉搜索树&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束条件&#xff1a; 节点的左子树仅包含键 小于 节点键的节点。 节点的右子树仅包含键 大于 节点键的节点。 左右子树也必须…

【计数DP】牛客小白月赛19

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先做法一定是计数 dp 然后状态设计&#xff0c;先设 dp[i] 然后看影响决策的因素&#xff1a;两边的火焰情况&#xff0c;那就 dp[i][0/1][0/1]表示 前 i 个&#xff0c;该位有无火焰&#xff0c;该位右边有无火焰的方案数…

Kioptrix-3

靶场下载地址 https://download.vulnhub.com/kioptrix/KVM3.rar 信息收集 # Nmap 7.94 scan initiated Thu Dec 21 21:52:25 2023 as: nmap -sn -oN live.nmap 192.168.1.0/24 Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00048s latency). MAC Address:…

2024年PMP考试新考纲-PMBOK第七版-项目管理原则真题解析(续2)

很多在备考2024年PMP考试的小伙伴问华研荟&#xff0c;从8月份以后把PMBOK第七版纳入PMP考试范围后&#xff0c;难不难&#xff1f;PMBOK第七版怎么考&#xff1f;尤其是第七版中的十二大项目管理原则读起来很晦涩难懂&#xff0c;这部分怎么考&#xff1f;该如何备考呢&#x…

Linux---基础操作命令

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

JavaWeb—html, css, javascript, dom,xml, tomcatservlet

文章目录 快捷键HTML**常用特殊字符替代:****标题****超链接标签****无序列表、有序列表****无序列表**:ul/li 基本语法**有序列表ol/li:****图像标签(img)**** 表格(table)标签****表格标签-跨行跨列表格****form(表单)标签介绍****表单form提交注意事项**div 标签p 标签sp…

Android可折叠设备完全指南:展开未来

Android可折叠设备完全指南&#xff1a;展开未来 探索如何使用Android Jetpack组件折叠和展开设备。 近年来&#xff0c;科技界见证了可折叠设备的革命性趋势。这些设备融合了便携性和功能性的创新特点&#xff0c;使用户能够在不同的形态之间无缝切换。在本博客中&#xff0c…

照片墙案例

整体效果&#xff1a; HTML部分&#xff1a; <body><div class"content"><header><h1>A silent world</h1><span>Image Wall with jQuery and CSS3</span></header><div class"iw_wrapper"><ul…

3D数字化系统建设

以3D可视化、数字化技术为基础&#xff0c;其实&#xff0c;很多传统的系统软件都可以重新做一下。 比如&#xff1a;以下这个使用场景&#xff1a;零售门店陈列&#xff1b; 还有&#xff0c;数字化仓储系统&#xff0c;3D数字化供应链系统&#xff0c;3D数字化的生产系统&a…

.NET中的Swagger使用

目录 前言 一、Swagger是什么&#xff1f; 二、如何Swagger文档说明的信息 1.在AddSwaggerGen方法中写入文档信息 2.运行效果 二、文档UI界面标题、路由设置 1.在中间件UseSwaggerUI方法中配置 三、文档UI界面添加接口注释 1.在 .csproj中配置 2.在AddSwaggerGen方法中配置Incl…

MFC 菜单

目录 MFC菜单 菜单使用 添加菜单资源 将菜单设置到窗口 ON_COMMAND消息处理 命令消息 WM_COMMAND 的处理顺序 设置菜单项状态 右键菜单 MFC菜单 在Win32编程中&#xff0c;使用菜单句柄 HMENU 来标识菜单&#xff0c;在MFC中使用CMenu类对象表示菜单。封装了关于菜单的…