BFS

宽度优先搜索

计算疫情扩散时间

感染区就相当于我们往水面扔了一颗石子,广度优先搜索就相当于荡起的一圈涟漪
而二叉树的 BFS 是只会向左右2侧泛起涟漪!!!

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static boolean[][] isVisited;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static int N;
    static int[][] arr;
    static int res;
    
    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        String[] str = in.nextLine().split(",");
        N = str.length;
        int count = (int) Math.pow(N, 0.5);
        isVisited = new boolean[count][count];
        arr = new int[count][count];
        int index = 0;
        int startWeak = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                arr[i][j] = Integer.parseInt(str[index++]);
                if (arr[i][j] == 1){
                    isVisited[i][j] = true;
                    deque.offer(new Integer[]{i, j});
                    startWeak++;
                }
            }
        }
        if (startWeak == 0 || startWeak == N){
            System.out.println(-1);
            return;
        }
        
        bfs();
        System.out.println(res - 1);
    }

    public static void bfs(){
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size > 0) {
                Integer[] peek = deque.poll();
                turnWeak(peek[0], peek[1]);
                size--;
            }
            res++;
        }
    }

    public static void turnWeak(int i, int j){
        if (i - 1 >= 0 && !isVisited[i - 1][j]){ //  上
           deque.offer(new Integer[]{i - 1, j});
           isVisited[i - 1][j] = true;
        }
        if (i + 1 < Math.sqrt(N) && !isVisited[i + 1][j]){  //  下
            deque.offer(new Integer[]{i + 1, j} );
            isVisited[i + 1][j] = true;

        }
        if (j - 1 >= 0 && !isVisited[i][j - 1]){ //  左
            deque.offer(new Integer[]{i, j - 1} );
            isVisited[i][j - 1] = true;

        }
        if (j + 1 < Math.sqrt(N) && !isVisited[i][j + 1]){
            deque.offer(new Integer[]{i, j + 1} );
            isVisited[i][j + 1] = true;

        }
    }
}

寻找最大价值的矿堆

注意:与二叉树的类比
二叉树队列添加的前提条件:peek.left 或者 peek.right 不为 null
而到了图中:则变为

  • 符合条件的
  • 之前没有访问过的
    注意在添加后,要将该点的状态更改为已访问
import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static boolean[][] isVisited;
    static int row;
    static int col;
    static int[][] arr;
    static int res;

    static Deque<Integer[]> deque = new ArrayDeque<>();

    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();
        while (in.hasNextLine()) {
            String s = in.nextLine();
            if ("".equals(s)) {
                break;
            }
            sb.append(s + " ");
        }
        String str = sb.toString().trim();
        String[] split = str.split(" ");
        row = split.length;
        col = split[0].length();
        isVisited = new boolean[row][col];
        arr = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = split[i].charAt(j) - '0';
            }
        }

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] > 0 && !isVisited[i][j]){
                    isVisited[i][j] = true;
                    deque.offer(new Integer[]{i, j});
                    res = Math.max(res, bfs());
                }
            }
        }


        System.out.println(res);
    }

    public static int bfs() {
        int sum = 0;
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size > 0) {
                Integer[] peek = deque.poll();
                sum += arr[peek[0]][peek[1]];
                getNearBy(peek[0], peek[1]);
                size--;
            }
        }
        return sum;
    }

    public static void getNearBy(int i, int j) {
        if (i - 1 >= 0 && arr[i - 1][j] > 0 && !isVisited[i - 1][j]) {  //  上
            isVisited[i - 1][j] = true;
            deque.offer(new Integer[]{i - 1, j});
        }

        if (i + 1 < row && arr[i + 1][j] > 0 && !isVisited[i + 1][j]) { //  下
            isVisited[i + 1][j] = true;
            deque.offer(new Integer[]{i + 1, j});
        }

        if (j - 1 >= 0 && arr[i][j - 1] > 0 && !isVisited[i][j - 1]) {  //  左
            isVisited[i][j - 1] = true;
            deque.offer(new Integer[]{i, j - 1});
        }

        if (j + 1 < col && arr[i][j + 1] > 0 && !isVisited[i][j + 1]) { //  右
            isVisited[i][j + 1] = true;
            deque.offer(new Integer[]{i, j + 1});
        }
    }
}

可以组成网络的服务器【类似矿堆】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static boolean[][] isVisited;
    static int[][] arr;

    static Deque<Integer[]> deque = new ArrayDeque<>();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        row = Integer.parseInt(split[0]);
        col = Integer.parseInt(split[1]);
        isVisited = new boolean[row][col];

        arr = new int[row][col];
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < row; i++) {
            sb.append(in.nextLine() + " ");
        }
        String[] temp = sb.toString().trim().split(" ");
        int index = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j]  = Integer.parseInt(temp[index++]);
            }
        }
        int res = 0;

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] > 0){
                    deque.offer(new Integer[]{i, j});
                    isVisited[i][j] = true;
                    res = Math.max(res, bfs());
                }
            }
        }
        System.out.println(res);
    }
    
    public static int bfs(){
        int sum = 0;
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){
                Integer[] peek = deque.poll();
                sum += arr[peek[0]][peek[1]];
                getRowCount(peek[0], peek[1]);
                size--;
            }
        }
        return sum;
    }

    public static void getRowCount(int i, int j){
        if (i - 1 >= 0 && !isVisited[i - 1][j] && arr[i - 1][j] > 0){
            deque.offer(new Integer[]{i - 1, j});
            isVisited[i - 1][j] = true;
        }

        if (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] > 0){
            deque.offer(new Integer[]{i + 1, j});
            isVisited[i + 1][j] = true;
        }

        if(j - 1 >= 0 && !isVisited[i][j - 1] && arr[i][j - 1] > 0){
            deque.offer(new Integer[]{i, j - 1});
            isVisited[i][j - 1] = true;
        }
        if (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] > 0){
            deque.offer(new Integer[]{i, j + 1});
            isVisited[i][j + 1] = true;
        }

    }
}

战场索敌

可以理解为:以2为边界,求0 和 1 的和,满足小于 K即可

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[][] arr;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static boolean[][] isVisited;
    static int N;
    static int row;
    static int col;

    public static void main(String[] args) {
          Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        row = Integer.parseInt(split[0]);
        col = Integer.parseInt(split[1]);
        isVisited = new boolean[row][col];
        N = Integer.parseInt(split[2]);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < row; i++) {
            String str = in.nextLine().replace(".", "0").replace("#", "2").replace("E", "1");
            sb.append(str);
        }
        int index = 0;
        String[] temp = sb.toString().split("");

        arr = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = Integer.parseInt(temp[index++]);
            }
        }
        int count = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] < 2 && !isVisited[i][j]){
                    deque.offer(new Integer[]{i, j});
                    isVisited[i][j] = true;
                    if (bfs() < N){
                      count++;
                    }
                }
            }
        }
        System.out.println(count);
    }
    public static int bfs(){
        int sum = 0;
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){
                Integer[] peek = deque.poll();
                sum += arr[peek[0]][peek[1]];
                addEnemy(peek[0], peek[1]);
                size--;
            }
        }
        return sum;
    }

    public static void addEnemy(int i, int j){
        if (i - 1 >=0 && !isVisited[i - 1][j] && arr[i - 1][j] < 2){
            deque.offer(new Integer[]{i - 1, j});
            isVisited[i - 1][j] = true;
        }

        if (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] < 2){
            deque.offer(new Integer[]{i + 1, j});
            isVisited[i + 1][j] = true;
        }

        if (j - 1 >=0 && !isVisited[i][j - 1] && arr[i][j - 1] < 2){
            deque.offer(new Integer[]{i, j - 1});
            isVisited[i][j - 1] = true;
        }
        if (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] < 2){
            deque.offer(new Integer[]{i, j + 1});
            isVisited[i][j + 1] = true;
        }
    }
}

宜居星球改造计划【扩散问题,开始要把符合的都先入队】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static boolean[][] isVisited;
    static int[][] arr;
    static int badCount;
    static int day;

    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();
        while (in.hasNextLine()){
            String s = in.nextLine();
            if ("".equals(s)){
                break;
            }
            sb.append(s + ",");
            row++;
        }
        String str = sb.toString().substring(0, sb.length() - 1).replace("YES", "0").replace("NO", "1").replace("NA", "2");
        col = str.split(",")[0].replace(" ", "").length();
        String[] split = str.split("[ ,]");
        isVisited = new boolean[row][col];

        int index = 0;
        arr = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = Integer.parseInt(split[index++]);
                if (arr[i][j] == 1){
                    badCount++;
                }
            }
        }
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] == 0 && !isVisited[i][j]){    // 扩散问题:开始就将符合的都放到 队列中
                    deque.offer(new Integer[]{i, j});
                    isVisited[i][j] = true;
                }
            }
        }
        bfs();

        if (badCount != 0){
            System.out.println(-1);
            return;
        }
        System.out.println(day - 1);
    }
    public static void bfs(){
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){
                Integer[] peek = deque.poll();
                addSpace(peek[0], peek[1]);
                size--;
            }
            day++;
        }
    }


    public static void addSpace(int i, int j){
        if (i - 1 >=0 && !isVisited[i - 1][j] && arr[i - 1][j] == 1){
            arr[i - 1][j] = 0;
            deque.offer(new Integer[]{i - 1, j});
            isVisited[i - 1][j] = true;
            badCount--;
        }

        if (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] == 1){
            arr[i + 1][j] = 0;

            deque.offer(new Integer[]{i + 1, j});
            isVisited[i + 1][j] = true;
            badCount--;
        }

        if (j - 1 >=0 && !isVisited[i][j - 1] && arr[i][j - 1] == 1){
            arr[i][j - 1] = 0;


            deque.offer(new Integer[]{i, j - 1});
            isVisited[i][j - 1] = true;
            badCount--;
        }
        if (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] == 1){
            arr[i][j + 1] = 0;


            deque.offer(new Integer[]{i, j + 1});
            isVisited[i][j + 1] = true;
            badCount--;
        }
    }
}

周末爬山

问题:
请问小明能爬到的最高峰多高,到该最高峰的最短步数,输出以空格分隔

  • 最高
  • 最短
    难点:
  1. 何时到达能到达的最高处
  • 到达整个数组的最大值
  • 到达能走到的最大值【未知,难道要遍历2次??】===> 遍历2次可以通过用例【在第二次遍历开始前,注意把 isVisited 重置为 false】
import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static int k;
    static int[][] arr;
    static boolean[][] isVisited;
    static int time = 0;
    static int max = 0;
    static Deque<Integer[]> deque = new ArrayDeque<>();

    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        row = Integer.parseInt(split[0]);
        col = Integer.parseInt(split[1]);
        isVisited = new boolean[row][col];
        arr = new int[row][col];
        k = Integer.parseInt(split[2]);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < row; i++) {
            sb.append(in.nextLine() + " ");
        }
        String[] temp = sb.toString().trim().split(" ");
        int index = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = Integer.parseInt(temp[index++]);
            }
        }
        deque.offer(new Integer[]{0, 0});
        isVisited[0][0] = true;
        bfs1();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                isVisited[i][j] = false;
            }
        }
        deque.offer(new Integer[]{0, 0});
        isVisited[0][0] = true;
        bfs2();
        if (max == 0){
            System.out.println("0" + " " + "0");
            return;
        }
        System.out.println(max + " " + time);
    }
   public static void bfs1(){
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){   //  每层的
                Integer[] peek = deque.poll();
                max = Math.max(max, arr[peek[0]][peek[1]]);
                getNearBy(peek[0], peek[1]);
                size--;
            }
        }
    }

    public static void bfs2(){
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){   //  每层的
                Integer[] peek = deque.poll();
                if (arr[peek[0]][peek[1]] == max){
                    return;
                }
                getNearBy(peek[0], peek[1]);
                size--;
            }
            time++;
        }
    }

    public static void getNearBy(int i, int j){
        int temp = arr[i][j];
        if (i - 1 >= 0 && !isVisited[i - 1][j] && Math.abs(arr[i - 1][j] - temp) <= k){
            isVisited[i - 1][j] = true;
            deque.offer(new Integer[]{i - 1, j});
        }

        if (i + 1 < row && !isVisited[i + 1][j] && Math.abs(arr[i + 1][j] - temp) <= k){
            isVisited[i + 1][j] = true;
            deque.offer(new Integer[]{i + 1, j});
        }
        if (j - 1 >= 0 && !isVisited[i][j - 1] && Math.abs(arr[i][j - 1] - temp) <= k){
            isVisited[i][j - 1] = true;
            deque.offer(new Integer[]{i, j - 1});
        }
        if (j + 1 < col && !isVisited[i][j + 1] && Math.abs(arr[i][j + 1] - temp) <= k){
            isVisited[i][j + 1] = true;
            deque.offer(new Integer[]{i, j + 1});
        }
    }
}

返回矩阵中非1元素个数

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static int[][] arr;
    static boolean[][] isVisited;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static int sum;


    public static void main(String[] args) {
          Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        row = Integer.parseInt(split[0]);
        col = Integer.parseInt(split[1]);
        arr = new int[row][col];
        isVisited = new boolean[row][col];
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < row; i++) {
            sb.append(in.nextLine() + " ");
        }
        int index = 0;
        String[] temp = sb.toString().trim().split(" ");
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = Integer.parseInt(temp[index++]);
            }
        }

        sum = row * col - 1;
        arr[0][0] = 1;
        isVisited[0][0] = true;
        deque.offer(new Integer[]{0, 0});
        bfs();
        System.out.println(sum);
    }

     public static void bfs(){
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){
                Integer[] peek = deque.poll();
                turnWeak(peek[0], peek[1]);
                size--;
            }
        }

    }

    public static void turnWeak(int i, int j){
        if (i - 1 >= 0 && !isVisited[i - 1][j] && arr[i - 1][j] != 2){
            isVisited[i - 1][j] = true;
            deque.offer(new Integer[]{i - 1, j});
            sum--;
        }

        if (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] != 2){
            isVisited[i + 1][j] = true;
            deque.offer(new Integer[]{i + 1, j});
            sum--;
        }

        if (j - 1 >= 0 && !isVisited[i][j - 1] && arr[i][j - 1] != 2){
            isVisited[i][j - 1] = true;
            deque.offer(new Integer[]{i, j - 1});
            sum--;
        }

        if (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] != 2){
            isVisited[i][j + 1] = true;
            deque.offer(new Integer[]{i, j + 1});
            sum--;
        }
    }
}

欢乐的周末

难点:

  1. 2个点要连通
  2. 以其中一个2为起点,开始入队,引入变量count表示2的个数
  • 如果最终count != 2,则说明不是连通的,输出0
  • 否则bfs 求和即可
  1. 注意 row 和 col的顺序
import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static int[][] arr;
    static boolean[][] isVisited;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static int count = 0;
    static int res = 0;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        col = Integer.parseInt(split[0]);
        row = Integer.parseInt(split[1]);
        arr = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = in.nextInt();
            }
        }

        isVisited = new boolean[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] == 2 && count == 0){
                    deque.offer(new Integer[]{i, j});
                    isVisited[i][j] = true;
                    bfs();
                }
            }
        }
        if (count != 2){
            System.out.println(0);
            return;
        }
        System.out.println((res - 4) / 3);
    }

    public static void bfs(){
        while (!deque.isEmpty()){
            int size = deque.size();
            while (size > 0){
                Integer[] peek = deque.poll();
                if (arr[peek[0]][peek[1]] == 2){
                    count++;    //  如果最终弹不出2个 2的话,找不到!!!
                }
                res += arr[peek[0]][peek[1]];
                getNearBy(peek[0], peek[1]);
                size--;
            }
        }
    }
    public static void getNearBy(int i, int j){
        while (i - 1 >= 0 && !isVisited[i- 1][j] && arr[i - 1][j] != 1){
            isVisited[i - 1][j] = true;
            deque.offer(new Integer[]{i - 1, j});
        }

        while (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] != 1){
            isVisited[i + 1][j] = true;
            deque.offer(new Integer[]{i + 1, j});
        }

        while (j - 1 >= 0 && !isVisited[i][j - 1] && arr[i][j - 1] != 1){
            isVisited[i][j - 1] = true;
            deque.offer(new Integer[]{i, j - 1});
        }

        while (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] != 1){
            isVisited[i][j + 1] = true;
            deque.offer(new Integer[]{i, j + 1});
        }
    }
}

力扣

200. 岛屿数量

注意字符间比大小,要用单引号 '1'

class Solution {
	int sum = 0;
	boolean[][] isVisited;
	int row;
	int col;
	Deque<Integer[]> deque = new ArrayDeque<>();
	public int numIslands(char[][] grid) {
    	row = grid.length;
    	col = grid[0].length;
    	isVisited = new boolean[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (grid[i][j] == '1' && !isVisited[i][j]){
					isVisited[i][j] = true;
					deque.offer(new Integer[]{i, j});
					sum++;
					bfs(grid);
				}
			}
		}

		return sum;
    }

    public void bfs(char[][] grid){
		while (!deque.isEmpty()){
			int size = deque.size();
			while (size > 0){
				Integer[] peek = deque.poll();
				getNearBy(peek[0], peek[1], grid);
				size--;
			}
		}
	}

    public void getNearBy(int i, int j, char[][] chars){
    	if (i - 1 >= 0 && !isVisited[i - 1][j] && chars[i - 1][j] == '1'){
    		isVisited[i - 1][j] = true;
    		deque.offer(new Integer[]{i - 1, j});
		}
		if (i + 1 < row && !isVisited[i + 1][j] && chars[i + 1][j] == '1'){
			isVisited[i + 1][j] = true;
			deque.offer(new Integer[]{i + 1, j});
		}

		if (j - 1 >= 0 && !isVisited[i][j - 1] && chars[i][j - 1] == '1'){
			isVisited[i][j - 1] = true;
			deque.offer(new Integer[]{i, j - 1});
		}

		if (j + 1 < col && !isVisited[i][j + 1] && chars[i][j + 1] == '1'){
			isVisited[i][j + 1] = true;
			deque.offer(new Integer[]{i, j + 1});
		}
	}
}

695. 岛屿的最大面积

class Solution {
	int res = 0;
	boolean[][] isVisited;
	int row;
	int col;
	Deque<Integer[]> deque = new ArrayDeque<>();
    public int maxAreaOfIsland(int[][] grid) {
		row = grid.length;
		col = grid[0].length;
		isVisited = new boolean[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (grid[i][j] == 1 && !isVisited[i][j]){
					isVisited[i][j] = true;
					deque.offer(new Integer[]{i, j});
					res = Math.max(res, bfs(grid));
				}
			}
		}

		return res;
    }

	public int bfs(int[][] grid){
    	int sum = 0;
		while (!deque.isEmpty()){
			int size = deque.size();
			while (size > 0){
				Integer[] peek = deque.poll();
				sum++;
				getNearBy(peek[0], peek[1], grid);
				size--;
			}
		}
		return sum;
	}

	public void getNearBy(int i, int j, int[][] chars){
		if (i - 1 >= 0 && !isVisited[i - 1][j] && chars[i - 1][j] == 1){
			isVisited[i - 1][j] = true;
			deque.offer(new Integer[]{i - 1, j});
		}
		if (i + 1 < row && !isVisited[i + 1][j] && chars[i + 1][j] == 1){
			isVisited[i + 1][j] = true;
			deque.offer(new Integer[]{i + 1, j});
		}

		if (j - 1 >= 0 && !isVisited[i][j - 1] && chars[i][j - 1] == 1){
			isVisited[i][j - 1] = true;
			deque.offer(new Integer[]{i, j - 1});
		}

		if (j + 1 < col && !isVisited[i][j + 1] && chars[i][j + 1] == 1){
			isVisited[i][j + 1] = true;
			deque.offer(new Integer[]{i, j + 1});
		}
	}
}

130. 被围绕的区域

找到边界的 'O',开始扩散,并标记为访问过,最后再将所有为标记过的 'O',改为 'X'

class Solution {
	int row;
	int col;
	boolean[][] isVisited;
	Deque<Integer[]> deque = new ArrayDeque<>();
	public void solve(char[][] board) {
		// https://leetcode.cn/problems/surrounded-regions/solutions/2213619/bao-li-sou-suo-suo-you-yu-bian-jie-shang-bz3f/
		row = board.length;
		col = board[0].length;
		isVisited = new boolean[row][col];
		//	找到边界的 O 然后扩散!!!
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (i == 0 || i == row - 1 || j == 0 || j == col - 1) {
					if (board[i][j] == 'O') {
						deque.offer(new Integer[]{i, j});
						isVisited[i][j] = true;
					}
				}
			}
		}

		bfs(board);
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (board[i][j] == 'O' && !isVisited[i][j]){	//	最后未被添加过的 'O' 重置为:'X'
					board[i][j] = 'X';
				}
			}
		}
	}

	public void bfs(char[][] grid){
		while (!deque.isEmpty()){
			int size = deque.size();
			while (size > 0){
				Integer[] peek = deque.poll();	//	弹出的所有都是不被包围的!!!
				getNearBy(peek[0], peek[1], grid);
				size--;
			}
		}
	}

	public void getNearBy(int i, int j, char[][] chars){
		if (i - 1 >= 0 && !isVisited[i - 1][j] && chars[i - 1][j] == 'O'){
			isVisited[i - 1][j] = true;
			deque.offer(new Integer[]{i - 1, j});
		}
		if (i + 1 < row && !isVisited[i + 1][j] && chars[i + 1][j] == 'O'){
			isVisited[i + 1][j] = true;
			deque.offer(new Integer[]{i + 1, j});
		}

		if (j - 1 >= 0 && !isVisited[i][j - 1] && chars[i][j - 1] == 'O'){
			isVisited[i][j - 1] = true;
			deque.offer(new Integer[]{i, j - 1});
		}

		if (j + 1 < col && !isVisited[i][j + 1] && chars[i][j + 1] == 'O'){
			isVisited[i][j + 1] = true;
			deque.offer(new Integer[]{i, j + 1});
		}
	}
}

1254. 统计封闭岛屿的数目【和上题类似】

要求的区域 = 0构成的所有区域 - 边界0的区域

class Solution {
	int res = 0;
	int count = 0;
	boolean[][] isVisited;
	int row;
	int col;
	Deque<Integer[]> deque = new ArrayDeque<>();

    public int closedIsland(int[][] grid) {
		row = grid.length;
		col = grid[0].length;
		isVisited = new boolean[row][col];

		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (grid[i][j] == 0 && !isVisited[i][j]) {
					count++;
					deque.offer(new Integer[]{i, j});
					isVisited[i][j] = true;
					bfs(grid);
				}
			}
		}

		for (int i = 0; i < row; i++) {
			Arrays.fill(isVisited[i], false);
		}


		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (i == 0 || i == row - 1 || j == 0 || j == col - 1){
					if (grid[i][j] == 0 && !isVisited[i][j]){
						deque.offer(new Integer[]{i, j});
						isVisited[i][j] = true;
						res++;
						bfs(grid);
					}
				}
			}
		}
		return count - res;
    }

	public void bfs(int[][] grid){
		while (!deque.isEmpty()){
			int size = deque.size();
			while (size > 0){
				Integer[] peek = deque.poll();
				getNearBy(peek[0], peek[1], grid);
				size--;
			}
		}
	}

	public void getNearBy(int i, int j, int[][] chars){
		if (i - 1 >= 0 && !isVisited[i - 1][j] && chars[i - 1][j] == 0){
			isVisited[i - 1][j] = true;
			deque.offer(new Integer[]{i - 1, j});
		}
		if (i + 1 < row && !isVisited[i + 1][j] && chars[i + 1][j] == 0){
			isVisited[i + 1][j] = true;
			deque.offer(new Integer[]{i + 1, j});
		}

		if (j - 1 >= 0 && !isVisited[i][j - 1] && chars[i][j - 1] == 0){
			isVisited[i][j - 1] = true;
			deque.offer(new Integer[]{i, j - 1});
		}

		if (j + 1 < col && !isVisited[i][j + 1] && chars[i][j + 1] == 0){
			isVisited[i][j + 1] = true;
			deque.offer(new Integer[]{i, j + 1});
		}
	}
}

994. 腐烂的橘子

class Solution {
	boolean[][] isVisited;
	int row;
	int col;
	int goodCount;
	int day;
	Deque<Integer[]> deque = new ArrayDeque<>();
	public int orangesRotting(int[][] grid) {
		row = grid.length;
		col = grid[0].length;
		isVisited = new boolean[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (grid[i][j] == 1){
					goodCount++;
				}
				if (grid[i][j] == 2){
					deque.offer(new Integer[]{i, j});
				}
			}
		}
		if (goodCount == 0){  //  如果一开始就没有好橘子了,返回 0天
			return 0;
		}
		
		bfs(grid);
		if (goodCount > 0){  //  有憋在死角的橘子,返回 - 1
			return -1;
		}

		return day - 1;  //  可以全部腐蚀,减去初始的那一天 day0
	}

	public void bfs(int[][] arr){
		while (!deque.isEmpty()){
			int len = deque.size();
			while (len > 0){
				Integer[] peek = deque.poll();
				goRound(arr, peek[0], peek[1]);
				len--;
			}
			day++;
		}
	}


	public void goRound(int[][] arr, int i, int j){
		if (i - 1 >= 0 && !isVisited[i - 1][j] && arr[i - 1][j] == 1){
			isVisited[i - 1][j] = true;
			goodCount--;
			deque.add(new Integer[]{i - 1, j});
		}
		if (i + 1 < row && !isVisited[i + 1][j] && arr[i + 1][j] == 1){
			isVisited[i + 1][j] = true;
			goodCount--;
			deque.add(new Integer[]{i + 1, j});
		}
		if (j - 1 >= 0 && !isVisited[i][j - 1] && arr[i][j - 1] == 1){
			isVisited[i][j - 1] = true;
			goodCount--;
			deque.add(new Integer[]{i, j - 1});
		}
		if (j + 1 < col && !isVisited[i][j + 1] && arr[i][j + 1] == 1){
			isVisited[i][j + 1] = true;
			goodCount--;
			deque.add(new Integer[]{i, j + 1});
		}
	}
}

矩阵扩散

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[][] offsets = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
    static boolean[][] isVisited;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static int[][] arr;
    static int row;
    static int col;
    static int day;

    public static void main(String[] args) {
         Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(",");
        row = Integer.parseInt(split[0]);
        col = Integer.parseInt(split[1]);
        arr = new int[row][col];
        int x1 = Integer.parseInt(split[2]);
        int y1 = Integer.parseInt(split[3]);
        int x2 = Integer.parseInt(split[4]);
        int y2 = Integer.parseInt(split[5]);
        isVisited = new boolean[row][col];
        isVisited[x1][y1] = true;
        isVisited[x2][y2] = true;
        deque.offer(new Integer[]{x1, y1});
        deque.offer(new Integer[]{x2, y2});
        bfs();
        System.out.println(day - 1);
    }
    public static void bfs(){
        while (!deque.isEmpty()){
            int len = deque.size();
            while (len > 0){
                Integer[] peek = deque.poll();
                goRound(peek[0], peek[1]);
                len--;
            }
            day++;
        }
    }
    public static void goRound(int i, int j){
        for (int[] offset : offsets) {
            int x = i + offset[0];
            int y = j + offset[1];
            if (x >= 0 && x < row && y >= 0 && y < col && !isVisited[x][y] && arr[x][y] == 0){
                deque.offer(new Integer[]{x, y});
                isVisited[x][y] = true;
            }
        }
    }
}

污染水域

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[][] offsets = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
    static boolean[][] isVisited;
    static Deque<Integer[]> deque = new ArrayDeque<>();
    static int[][] arr;
    static int N;
    static int day;

    public static void main(String[] args) {
         Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(",");
        int len = split.length;
        N = (int)Math.sqrt(len);
        arr = new int[N][N];
        isVisited = new boolean[N][N];
        int index = 0;
        int temp = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                arr[i][j] = Integer.parseInt(split[index++]);
                if (!isVisited[i][j] && arr[i][j] == 1){
                    temp++;
                    deque.offer(new Integer[]{i, j});
                    isVisited[i][j] = true;
                }
            }
        }
        if (temp == 0 || temp == len){
            System.out.println(-1);
            return;
        }

        bfs();
        System.out.println(day - 1);
    }
    public static void bfs(){
        while (!deque.isEmpty()){
            int len = deque.size();
            while (len > 0){
                Integer[] peek = deque.poll();
                goRound(peek[0], peek[1]);
                len--;
            }
            day++;
        }
    }
    public static void goRound(int i, int j){
        for (int[] offset : offsets) {
            int x = i + offset[0];
            int y = j + offset[1];
            if (x >= 0 && x < N && y >= 0 && y < N && !isVisited[x][y] && arr[x][y] == 0){
                deque.offer(new Integer[]{x, y});
                isVisited[x][y] = true;
            }
        }
    }
}
posted @ 2023-09-11 15:55  爱新觉罗LQ  阅读(10)  评论(0编辑  收藏  举报