求01矩阵连通域大小(C++、新华智云笔试题)

凉了,so sad.


十月份一直在整论文的事儿,工作方面的东西没看,题也没做,结果就是碰到手撕代码就挂QAQ
也许碰到以前做过的类型题思路会好点,但是这个题也没做过,就硬想,结果只想出了漏洞百出的思路。
题目如下:

问题描述:
给定一个M*N的矩阵,里面有数字10+ 然后给定一个坐标:(x, y)。
请写一个程序计算与坐标x, y值相同,且连通的数字个数。
“连通” 定义为:左右或者上下数值一样则认为这两个块是连通的,连通具有传递性。

输入:matrix, x, y
输出:n

举例:
输入:
matrix = [
	[1, 0, 1, 0]
	[1, 0, 0, 0]
	[1, 1, 0, 1]
	[0, 1, 0, 1]
	[1, 1, 0, 0]
}

我当时想到的思路就是去判断目标点(x,y)周围的十字方向的四个点是否连通,如果连通则继续递归判断。
当时手撕没撕出来(写的什么稀烂代码),就直接给面试官讲了思路,面试官听完回了一句,有个条件你没提到。
然后我当时就懵了,没想到自己已经那么菜了。

结束之后我百度了才发现,如果按照我的简单思路来写的话,是很容易重复遍历的,比如目标点的左侧,上侧,以及左上侧三个点都和目标点连通的话,那么就出现了无限递归死循环的情况。所以必须再利用一个mask来统计已遍历过的点,避免出现重复遍历导致死循环的出现。

以下内容和代码主要参考这篇博客
这样的无向图遍历问题主要采用BFS广度优先搜索实现。主要思路为:

  • 先访问目标点的值,并进入队列。
  • 然后访问该元素的四邻域,如果是连通的话,就进入到队列中。
  • 取出队列中的点,继续上一步操作,直至遍历完成。

实际代码实现采用队列居多,leetcode上有很多这样的题目。代码框架是:

vector<int> tmp; //结果
vector<int> mask  // 用于不再访问之前访问过的元素
queue<int>  q;  //用于存储当前的连通域
q.push(...);  //将第一个合适的解压入
while(! q.empty())
{
    int t = q.front();
    q.pop();
    if(t == 你想要的结果)
    { 
        tmp.push_back(...)
        mask[... ] = true;
    }
    if( mask[ i+1] == false)  //保证访问的元素之前没有访问过,如果合适,就加入到队列中
    	q.push(...)
}

根据题目要求重新写了代码。
完整代码为:

#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;

// 判断该点是否已被遍历过或是坐标越界
bool check(vector<vector<int>>& matrix, vector<vector<bool>>& mask, int x, int y, int value) {
	return x >= 0 && y >= 0 && x < matrix.size() && y < matrix[0].size() && matrix[x][y] == value && mask[x][y] != true;
}
// 如果该点未越界且未被遍历过,则统计加1,将其加入队列继续检索
void add(vector<vector<int>>& matrix, vector<vector<bool>>& mask, queue<pair<int, int>>& q, int x, int y, int value, int& result) {
	if (check(matrix, mask, x, y, value)) {
		result += 1;
		q.push(pair<int, int>{x, y});
		mask[x][y] = true;
	}
}
int main() {
	vector<vector<int>> matrix{ {1, 0, 1, 0},{1, 0, 0, 0},{1, 1, 0, 1},{0, 1, 0, 1},{1, 1, 0, 0} };
	vector<vector<bool>> mask(matrix.size(), vector<bool>(matrix[0].size(), false));
	queue <pair<int, int>> q;
	int result = 1;
	int x = 2;
	int y = 2;
	int value = matrix[x][y];
	cout << value << endl;
	pair<int, int> temp;
	mask[x][y] = true;
	q.push(pair<int, int>{x, y});
	while (!q.empty()) {
		temp = q.front();
		q.pop();
		add(matrix, mask, q, temp.first, temp.second + 1, value, result);
		add(matrix, mask, q, temp.first, temp.second - 1, value, result);
		add(matrix, mask, q, temp.first - 1, temp.second, value, result);
		add(matrix, mask, q, temp.first + 1, temp.second, value, result);
	}
	cout << result << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值