找出由‘1’组成的孤岛
面试题目,来自leetcode,曾经败在了这个简单的小题。。
Given a 2d grid map of '1'
s (land) and '0'
s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110
11010
11000
00000
Answer: 1
Example 2:
11000
11000
00100
00011
Answer: 3
、、、、、、、、、、、、My accepted Answer 1、、、、、、、、、、、、、、
遍历整个数组,如果发现‘1’就将其及其临接的‘1’修改为0,就是这样。
int numIslands(char** grid, int gridRowSize, int gridColSize) {
int Islands_Num = 0;
for(int rowIdx = 0; rowIdx < gridRowSize; rowIdx++)
{
for(int columIdx = 0; columIdx < gridColSize; columIdx++)
{
if('1' == grid[rowIdx][columIdx])
{
ConverToZero(grid,rowIdx, columIdx, gridRowSize, gridColSize);
Islands_Num++;
}
}
}
return Islands_Num;
}
void ConverToZero(char** grid, int rowIdx, int columIdx, int gridRowSize, int gridColSize)
{
if( (rowIdx >= gridRowSize)||(columIdx >= gridColSize) ||(rowIdx < 0)||(columIdx < 0) )
return;
if('1' == grid[rowIdx][columIdx])
{
grid[rowIdx][columIdx] = '0';
}
else
return;
ConverToZero(grid,rowIdx+1,columIdx, gridRowSize,gridColSize );
ConverToZero(grid,rowIdx-1,columIdx, gridRowSize,gridColSize );
ConverToZero(grid,rowIdx,columIdx+1, gridRowSize,gridColSize );
ConverToZero(grid,rowIdx,columIdx-1, gridRowSize,gridColSize );
}
、、、、、、、、、、、、时隔1年,闷头做出My accepted Answer2、、、、、、、、、、、、、、
遍历整个数组,发现1则以此处为基准不断向右,向下扩展去找相邻的1。同时,将被访问过的位置进行标记。
#pragma once
#include <iostream>
#include <vector>
class calIsland
{
public:
calIsland();
~calIsland();
std::vector<int> vInt;
int mColumSize = 0;
int mRowSize = 0;
void setArray(std::vector<int>& array,int rowSize, int columSize)
{
vInt = array;
mColumSize = columSize;
mRowSize = rowSize;
}
void prinArray()
{
for (int i = 0; i < mRowSize;++i)
{
for (int j = 0; j < mColumSize; ++j)
{
std::cout << " " << getVal(i,j);
}
std::cout << std::endl;
}
}
int getVal(int rowIdx, int columIdx)
{
int idx = mColumSize * rowIdx + columIdx;
return vInt.at(idx);
}
void mark(int rowIdx, int columIdx)
{
int idx = mColumSize * rowIdx + columIdx;
vInt[idx] = -1;
}
int expand(int i, int j)
{
if (i >= mRowSize || j >= mColumSize)
{
return 0;
}
if (-1 == getVal(i, j))
{
return 0;
}
int val = getVal(i, j);
mark(i,j);
if (0 == val)
{
return 0;
}
expand(i+1,j);
expand(i , j + 1);
return 1;
}
int solve()
{
int res = 0;
for (int i = 0; i < mRowSize; ++i)
{
for (int j = 0; j < mColumSize; ++j)
{
res += expand(i,j);
}
}
return res;
}
};
验证:
calIsland callIsLandObj;
std::vector<int> array = {1,1,0,0,1,1,0,0,0,0,1,0,1,1,0,1};
callIsLandObj.setArray(array, 4,4);
callIsLandObj.prinArray();
std::cout << "res="<<callIsLandObj.solve()<<std::endl;
2020.04
void expand(const vector<vector<int>>& arr, vector<vector<bool>> &mark, int row, int column,int i,int j) {
if (i >= row) {
return;
}
if (j >= column) {
return;
}
mark[i][j] = true;
if (j+1< column && arr[i][j + 1]){
expand(arr,mark,row, column,i,j+1);
}
if ( i+1<row &&arr[i+1][j]) {
expand(arr,mark, row, column, i+1, j);
}
}
int calIsland(const vector<vector<int>>& arr, int row, int column) {
if (arr.empty())
return 0;
int num = 0;
vector<vector<bool>> mark(row, vector<bool>(column,false));//true: has been accessed.
for (int i = 0; i < row; ++i) {
for (int j = 0; j < column; ++j) {
//mark[i][j] = true;
if (arr[i][j] == 1 && !mark[i][j]) {
num++;
expand(arr,mark,row,column, i, j);
}
}
}
return num;
}
int main() {
vector<vector<int>> arr(3, vector<int>(3, 0));
arr[0][0] = 1; arr[0][1] = 1; arr[0][2] = 0;
arr[1][0] = 0; arr[1][1] = 1; arr[1][2] = 1;
arr[2][0] = 0; arr[2][1] = 0; arr[2][2] = 1;
int num = calIsland(arr,3,3);
return 1;
}
找出由‘1’组成的孤岛的bounding box
以一个m*n矩阵的方式给出一个黑白图像(1代表黑,0代表白),需要用长方形框出所有联通的黑色物体,任何一个像素和其上下左右四个像素是联通的。用(x, y)代表一个像素,x为行编号,第一行为0,向下递增,y为列编号,第一列为0,向右递增。长方形用左上像素坐标和右下像素坐标表示。
比如下面这个4*9的图:
000111011
001110001
001001001
001000111
有3个框,((0,2), (3,5)), ((2,5), (2,5)), ((0,6), (3,8))。
要求写一个函数GetBoundingBox。 输入参数为int m, int n, int pic[][] 输出为std::vector<Box>, 其中,Box定义如下:
struct Box {
int min_x;
int min_y;
int max_x;
int max_y;
};
#include <iostream>
#include <vector>
using namespace std;
//以pic[stRow][stColu]为起始,找出1构成的区块。 递归。
void expand(int stRow, int stColu, int row, int column, vector<vector<int>>& pic,
int& leftCol, int& righCol, int& topRow, int& bottRow, vector<vector<bool>>& mark) {
if (mark[stRow][stColu]) // 如果已经被访问过,则直接返回,因为后面有四个if,是向四个方向发散的
return;
mark[stRow][stColu] = true;
if (stRow + 1< row && pic[stRow + 1][stColu]) {//下方的元素如果是1,则以下方的元素为始,继续递归
expand(stRow + 1, stColu, row, column, pic,
leftCol, righCol, topRow, bottRow, mark);
if(bottRow< stRow + 1) //更新bottRow
bottRow = stRow + 1;
}
if (stColu + 1< column && pic[stRow][stColu+1]) {
expand(stRow , stColu + 1, row, column, pic,
leftCol, righCol, topRow, bottRow, mark);
if(righCol< stColu + 1)
righCol = stColu + 1;
}
if (stRow - 1 >=0&&pic[stRow-1][stColu]) {
expand(stRow-1, stColu, row, column, pic,
leftCol, righCol, topRow, bottRow, mark);
if(topRow > stRow - 1)
topRow = stRow - 1;
}
if (stColu - 1 >=0&&pic[stRow][stColu - 1]) {
expand(stRow, stColu - 1, row, column, pic,
leftCol, righCol, topRow, bottRow, mark);
if(leftCol > stColu - 1)
leftCol = stColu - 1;
}
}
//pic: 二维数组
//row: 数组的行数
//column:数组的列数
std::vector<Box> GetBoundingBox(int row, int column, vector<vector<int>>& pic) {
vector<vector<bool>> mark(row, vector<bool>(column, false));//mark[i][j] == true, when pic[i][j] has been visited!
std::vector<Box> resultVec;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (!mark[i][j] && pic[i][j]) { //如果mark[i][j]没有被访问过,且,pic[i,j]=1,则开始以此元素为始,找出相连接的1的区块
int leftCol = j;//区块的最左侧元素的列
int righCol = j;
int topRow = i;//区块的最上方元素的行
int bottRow = i;
expand(i,j, row,column,pic, leftCol, righCol, topRow, bottRow, mark);
Box ob;
ob.min_x = topRow;
ob.max_x = bottRow;
ob.min_y = leftCol;
ob.max_y = righCol;
resultVec.push_back(std::move(ob));
}
}
}
return resultVec;
}
Test:
int main() {
vector<vector<int>> vec(4, vector<int>(9,0));
int row = 0;
vec[row][0] = 0; vec[row][1] = 0; vec[row][2] = 0; vec[row][3] = 1; vec[row][4] = 1; vec[row][5] = 1; vec[row][6] = 0; vec[row][7] = 1; vec[row][8] = 1;
row = 1;
vec[row][0] = 0; vec[row][1] = 0; vec[row][2] = 1; vec[row][3] = 1; vec[row][4] =1; vec[row][5] = 0; vec[row][6] = 0; vec[row][7] = 0; vec[row][8] = 1;
row = 2;
vec[row][0] = 0; vec[row][1] = 0; vec[row][2] = 1; vec[row][3] = 0; vec[row][4] = 0; vec[row][5] = 1; vec[row][6] = 0; vec[row][7] = 0; vec[row][8] = 1;
row = 3;
vec[row][0] = 0; vec[row][1] = 0; vec[row][2] = 1; vec[row][3] = 0; vec[row][4] = 0; vec[row][5] = 0; vec[row][6] = 1; vec[row][7] =1; vec[row][8] = 1;
std::vector<Box> boxes = GetBoundingBox(4, 9, vec);
for (const auto& it : boxes) {
cout << "topLeftPoint.x =" << it.min_x << " topLeftPoint.y =" << it.min_y
<< " rightBottomPoint.x =" << it.max_x << " rightBottomPoint.y =" << it.max_y;
cout << endl;
}
}
ouput: