二維矩陣中1所構成的塊個數(孤島問題),進行了總結。轉載請注明連結,有問題請及時聯系部落客:Alliswell_WP
》問題描述:給定一個n*n的矩陣裡面是0或1算出裡面獨立的0群組的數量。比如
0 0 1 1 1
0 1 1 1 0
1 1 1 1 0
1 0 1 1 1
1 1 1 1 1
答案:3。》思路:雖然不是圖,但是仍然可以用圖的DFS思想。更沒有必要用實作它對應的圖。為了計數同時為了節省空間,把矩陣的元素本身來作為DFS時使用的标記量visited[ ]。
(1)采用深度優先搜尋,周遊1在數組中的位置,對于周遊得到的1,先将其置位0再遞歸周遊該位置周圍8個方向上是否為1,如果為1将其值變為0。這樣順次得到的1的個數就為最終結果;
(2)标注法:用count變量标注塊的編号。從左到右從上到下周遊數組,對于值為1的位置,如果其左上,上,右上,左都為0,那麼該位置的值變為count+1;否則該位置的值變為其左上,上,右上,左位置的值。最後根據count就可以求得塊的個數。
(3)通過并查集解決;
上面方法的時間複雜度都為O(n)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
const int row = 5, col = 5;
//圖的DFS,把所有連通結點标記為count
void DFS(int m[][col], int i, int j, int row, int col, int count)
{
m[i][j] = count;
if (i>0 && m[i - 1][j] == 0)
{
DFS(m, i - 1, j, row, col, count);
}
if (j>0 && m[i][j - 1] == 0)
{
DFS(m, i, j - 1, row, col, count);
}
if (i<row - 1 && m[i + 1][j] == 0)
{
DFS(m, i + 1, j, row, col, count);
}
if (j<col - 1 && m[i][j + 1] == 0)
{
DFS(m, i, j + 1, row, col, count);
}
}
//對每個"為0且沒有被标記"的結點進行DFS
int get_group(int m[][col], int row, int col)
{
int count = 1; //01都被占用了,是以從2起始吧
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
if (m[i][j] == 0)
{
count++;
DFS(m, i, j, row, col, count);
}
}
}
return count - 1;//我是從2起始的
}
void display(int m[][5])
{
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
printf("%d ", m[i][j]);
printf("\n");
}
}
int main()
{
#if 0
//手工輸入矩陣的方式
int(*m)[col] = (int(*)[col])malloc(sizeof(int)*row*col);
for (int i = 0; i<row; i++)
for (int j = 0; j<col; j++)
scanf("%d", &m[i][j]);
#endif
#if 1
//二維數組初始化的方式
int m[][col] = { { 0,0,1,1,1 },
{ 0,1,1,1,0 },
{ 1,1,0,1,0 },
{ 1,0,1,0,0 },
{ 1,0,0,0,1 } };
#endif
display(m);
printf("%d\n", get_group(m, row, col));
display(m);
system("pause");
return 0;
}
》代碼優化:改為手動輸入二維矩陣的行數、列數和二維矩陣中0/1元素。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include<iostream>
using namespace std;
//const int row = 5, col = 5;
static int row , col;
//圖的DFS,把所有連通結點标記為count
void DFS(int **m, int i, int j, int row, int col, int count)
{
m[i][j] = count;
if (i>0 && m[i - 1][j] == 0)
{
DFS(m, i - 1, j, row, col, count);
}
if (j>0 && m[i][j - 1] == 0)
{
DFS(m, i, j - 1, row, col, count);
}
if (i<row - 1 && m[i + 1][j] == 0)
{
DFS(m, i + 1, j, row, col, count);
}
if (j<col - 1 && m[i][j + 1] == 0)
{
DFS(m, i, j + 1, row, col, count);
}
}
//對每個"為0且沒有被标記"的結點進行DFS
int get_group(int **m, int row, int col)
{
int count = 1; //01都被占用了,是以從2起始吧
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
if (m[i][j] == 0)
{
count++;
DFS(m, i, j, row, col, count);
}
}
}
return count - 1;//我是從2起始的
}
void display(int **m, int row, int col)
{
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
printf("%d ", m[i][j]);
printf("\n");
}
}
int main()
{
#if 1
//手工輸入矩陣的方式
cin >> row >> col;
int **m;
m = new int*[row]; //注意,int*[10]表示一個有10個元素的指針數組
for (int i = 0; i < row; ++i)
{
m[i] = new int[col];
}
//int(*m)[col] = (int(*)[col])malloc(sizeof(int)*row*col);
for (int i = 0; i<row; i++)
for (int j = 0; j<col; j++)
scanf("%d", &m[i][j]);
#endif
#if 0
//二維數組初始化的方式
int m[][col] = { { 0,0,1,1,1 },
{ 0,1,1,1,0 },
{ 1,1,0,1,0 },
{ 1,0,1,0,0 },
{ 1,0,0,0,1 } };
#endif
display(m,row, col);
printf("%d\n", get_group(m, row, col));
display(m, row, col);
for (int i = 0; i < col; i++)
{
delete[] m[i];
}
delete[] m;
system("pause");
return 0;
}