3640.三段式数组II

目标

给你一个长度为 n 的整数数组 nums。

三段式子数组 是一个连续子数组 nums[l...r](满足 0 <= l < r < n),并且存在下标 l < p < q < r,使得:

  • nums[l...p] 严格 递增,
  • nums[p...q] 严格 递减,
  • nums[q...r] 严格 递增。

请你从数组 nums 的所有三段式子数组中找出和最大的那个,并返回其 最大 和。

示例 1:

输入:nums = [0,-2,-1,-3,0,2,-1]
输出:-4
解释:
选择 l = 1, p = 2, q = 3, r = 5:
nums[l...p] = nums[1...2] = [-2, -1] 严格递增 (-2 < -1)。
nums[p...q] = nums[2...3] = [-1, -3] 严格递减 (-1 > -3)。
nums[q...r] = nums[3...5] = [-3, 0, 2] 严格递增 (-3 < 0 < 2)。
和 = (-2) + (-1) + (-3) + 0 + 2 = -4。

示例 2:

输入: nums = [1,4,2,7]
输出: 14
解释:
选择 l = 0, p = 1, q = 2, r = 3:
nums[l...p] = nums[0...1] = [1, 4] 严格递增 (1 < 4)。
nums[p...q] = nums[1...2] = [4, 2] 严格递减 (4 > 2)。
nums[q...r] = nums[2...3] = [2, 7] 严格递增 (2 < 7)。
和 = 1 + 4 + 2 + 7 = 14。

说明:

  • 4 <= n = nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9
  • 保证至少存在一个三段式子数组。

思路

3637.三段式数组I 判断是否是三段式数组,本题则是计算数组的三段式子数组的最大和。

定义 dp[k][i] 表示第 k 段以 i 结尾的前 k 段子数组的最大和,其中 k ∈ [0.2]。由于每一段至少有两个元素,如果 i - 1 是该段的起始,根据前面的定义,应该属于 k - 1 段。因此有 dp[k][i] = Math.max(dp[k - 1][i - 1], dp[k][i - 1]) + nums[i],当 k = 0 时,将 dp[k - 1][i - 1] 替换为 nums[i - 1] 即可。如果处于严格递增段,可以是第一段或第三段,如果处于严格递减段,则只能是第二段。

代码


/**
 * @date 2026-02-04 8:57
 */
public class MaxSumTrionic3640 {

    public long maxSumTrionic(int[] nums) {
        int n = nums.length;
        long[][] dp = new long[3][n];
        for (int k = 0; k < 3; k++) {
            Arrays.fill(dp[k], Long.MIN_VALUE / 2);
        }
        long res = Long.MIN_VALUE / 2;
        for (int i = 1; i < n; i++) {
            if (nums[i] > nums[i - 1]) {
                dp[0][i] = Math.max(nums[i - 1], dp[0][i - 1]) + nums[i];
                dp[2][i] = Math.max(dp[1][i - 1], dp[2][i - 1]) + nums[i];
            } else if (nums[i] < nums[i - 1]) {
                dp[1][i] = Math.max(dp[0][i - 1], dp[1][i - 1]) + nums[i];
            }
            res = Math.max(res, dp[2][i]);
        }
        return res;
    }

}

性能

3013.将数组分成最小总代价的子数组II

目标

给你一个下标从 0 开始长度为 n 的整数数组 nums 和两个 正 整数 k 和 dist 。

一个数组的 代价 是数组中的 第一个 元素。比方说,[1,2,3] 的代价为 1 ,[3,4,1] 的代价为 3 。

你需要将 nums 分割成 k 个 连续且互不相交 的子数组,满足 第二 个子数组与第 k 个子数组中第一个元素的下标距离 不超过 dist 。换句话说,如果你将 nums 分割成子数组 nums[0..(i1 - 1)], nums[i1..(i2 - 1)], ..., nums[ik-1..(n - 1)] ,那么它需要满足 ik-1 - i1 <= dist 。

请你返回这些子数组的 最小 总代价。

示例 1:

输入:nums = [1,3,2,6,4,2], k = 3, dist = 3
输出:5
解释:将数组分割成 3 个子数组的最优方案是:[1,3] ,[2,6,4] 和 [2] 。这是一个合法分割,因为 ik-1 - i1 等于 5 - 2 = 3 ,等于 dist 。总代价为 nums[0] + nums[2] + nums[5] ,也就是 1 + 2 + 2 = 5 。
5 是分割成 3 个子数组的最小总代价。

示例 2:

输入:nums = [10,1,2,2,2,1], k = 4, dist = 3
输出:15
解释:将数组分割成 4 个子数组的最优方案是:[10] ,[1] ,[2] 和 [2,2,1] 。这是一个合法分割,因为 ik-1 - i1 等于 3 - 1 = 2 ,小于 dist 。总代价为 nums[0] + nums[1] + nums[2] + nums[3] ,也就是 10 + 1 + 2 + 2 = 15 。
分割 [10] ,[1] ,[2,2,2] 和 [1] 不是一个合法分割,因为 ik-1 和 i1 的差为 5 - 1 = 4 ,大于 dist 。
15 是分割成 4 个子数组的最小总代价。

示例 3:

输入:nums = [10,8,18,9], k = 3, dist = 1
输出:36
解释:将数组分割成 4 个子数组的最优方案是:[10] ,[8] 和 [18,9] 。这是一个合法分割,因为 ik-1 - i1 等于 2 - 1 = 1 ,等于 dist 。总代价为 nums[0] + nums[1] + nums[2] ,也就是 10 + 8 + 18 = 36 。
分割 [10] ,[8,18] 和 [9] 不是一个合法分割,因为 ik-1 和 i1 的差为 3 - 1 = 2 ,大于 dist 。
36 是分割成 3 个子数组的最小总代价。

说明:

  • 3 <= n <= 10^5
  • 1 <= nums[i] <= 10^9
  • 3 <= k <= n
  • k - 2 <= dist <= n - 2

思路

定义数组的代价是其第一个元素值,有一个数组 nums,将其分割成 k 个连续且不相交的子数组,并且要求第 2 个子数组 与 第 k 个子数组的第一个元素的下标的距离不超过 dist,求子数组的最小总代价。

//todo

代码

性能

2977.转换字符串的最小成本II

目标

给你两个下标从 0 开始的字符串 source 和 target ,它们的长度均为 n 并且由 小写 英文字母组成。

另给你两个下标从 0 开始的字符串数组 original 和 changed ,以及一个整数数组 cost ,其中 cost[i] 代表将字符串 original[i] 更改为字符串 changed[i] 的成本。

你从字符串 source 开始。在一次操作中,如果 存在 任意 下标 j 满足 cost[j] == z 、original[j] == x 以及 changed[j] == y ,你就可以选择字符串中的 子串 x 并以 z 的成本将其更改为 y 。 你可以执行 任意数量 的操作,但是任两次操作必须满足 以下两个 条件 之一 :

  • 在两次操作中选择的子串分别是 source[a..b] 和 source[c..d] ,满足 b < c 或 d < a 。换句话说,两次操作中选择的下标 不相交 。
  • 在两次操作中选择的子串分别是 source[a..b] 和 source[c..d] ,满足 a == c 且 b == d 。换句话说,两次操作中选择的下标 相同 。

返回将字符串 source 转换为字符串 target 所需的 最小 成本。如果不可能完成转换,则返回 -1 。

注意,可能存在下标 i 、j 使得 original[j] == original[i] 且 changed[j] == changed[i] 。

示例 1:

输入:source = "abcd", target = "acbe", original = ["a","b","c","c","e","d"], changed = ["b","c","b","e","b","e"], cost = [2,5,5,1,2,20]
输出:28
解释:将 "abcd" 转换为 "acbe",执行以下操作:
- 将子串 source[1..1] 从 "b" 改为 "c" ,成本为 5 。
- 将子串 source[2..2] 从 "c" 改为 "e" ,成本为 1 。
- 将子串 source[2..2] 从 "e" 改为 "b" ,成本为 2 。
- 将子串 source[3..3] 从 "d" 改为 "e" ,成本为 20 。
产生的总成本是 5 + 1 + 2 + 20 = 28 。 
可以证明这是可能的最小成本。

示例 2:

输入:source = "abcdefgh", target = "acdeeghh", original = ["bcd","fgh","thh"], changed = ["cde","thh","ghh"], cost = [1,3,5]
输出:9
解释:将 "abcdefgh" 转换为 "acdeeghh",执行以下操作:
- 将子串 source[1..3] 从 "bcd" 改为 "cde" ,成本为 1 。
- 将子串 source[5..7] 从 "fgh" 改为 "thh" ,成本为 3 。可以执行此操作,因为下标 [5,7] 与第一次操作选中的下标不相交。
- 将子串 source[5..7] 从 "thh" 改为 "ghh" ,成本为 5 。可以执行此操作,因为下标 [5,7] 与第一次操作选中的下标不相交,且与第二次操作选中的下标相同。
产生的总成本是 1 + 3 + 5 = 9 。
可以证明这是可能的最小成本。

示例 3:

输入:source = "abcdefgh", target = "addddddd", original = ["bcd","defgh"], changed = ["ddd","ddddd"], cost = [100,1578]
输出:-1
解释:无法将 "abcdefgh" 转换为 "addddddd" 。
如果选择子串 source[1..3] 执行第一次操作,以将 "abcdefgh" 改为 "adddefgh" ,你无法选择子串 source[3..7] 执行第二次操作,因为两次操作有一个共用下标 3 。
如果选择子串 source[3..7] 执行第一次操作,以将 "abcdefgh" 改为 "abcddddd" ,你无法选择子串 source[1..3] 执行第二次操作,因为两次操作有一个共用下标 3 。

说明:

  • 1 <= source.length == target.length <= 1000
  • source、target 均由小写英文字母组成
  • 1 <= cost.length == original.length == changed.length <= 100
  • 1 <= original[i].length == changed[i].length <= source.length
  • original[i]、changed[i] 均由小写英文字母组成
  • original[i] != changed[i]
  • 1 <= cost[i] <= 10^6

思路

代码

性能

3651.带传送的最小路径成本

目标

给你一个 m x n 的二维整数数组 grid 和一个整数 k。你从左上角的单元格 (0, 0) 出发,目标是到达右下角的单元格 (m - 1, n - 1)。

有两种移动方式可用:

  • 普通移动:你可以从当前单元格 (i, j) 向右或向下移动,即移动到 (i, j + 1)(右)或 (i + 1, j)(下)。成本为目标单元格的值。
  • 传送:你可以从任意单元格 (i, j) 传送到任意满足 grid[x][y] <= grid[i][j] 的单元格 (x, y);此移动的成本为 0。你最多可以传送 k 次。

返回从 (0, 0) 到达单元格 (m - 1, n - 1) 的 最小 总成本。

示例 1:

输入: grid = [[1,3,3],[2,5,4],[4,3,5]], k = 2
输出: 7
解释:
我们最初在 (0, 0),成本为 0。
当前位置    移动           新位置      总成本
(0, 0)    向下移动        (1, 0)     0 + 2 = 2
(1, 0)    向右移动        (1, 1)     2 + 5 = 7
(1, 1)    传送到(2, 2)    (2, 2)     7 + 0 = 7
到达右下角单元格的最小成本是 7。

示例 2:

输入: grid = [[1,2],[2,3],[3,4]], k = 1
输出: 9
解释:
我们最初在 (0, 0),成本为 0。
当前位置    移动       新位置     总成本
(0, 0)    向下移动    (1, 0)    0 + 2 = 2
(1, 0)    向右移动    (1, 1)    2 + 3 = 5
(1, 1)    向下移动    (2, 1)    5 + 4 = 9
到达右下角单元格的最小成本是 9。

说明:

  • 2 <= m, n <= 80
  • m == grid.length
  • n == grid[i].length
  • 0 <= grid[i][j] <= 10^4
  • 0 <= k <= 10

思路

有一个 m x n 的二维矩阵 grid,可以向右/向下移动,每次移动的成本为目标单元格的值。此外,在任意单元格 (i, j),可以 零成本 传送到任意满足条件 (grid[x][y] <= grid[i][j]) 的单元格 (x, y)。求从 (0, 0) 出发最多传送 k 次到达 (m - 1, n - 1) 的最小成本。

定义 dp[i][j][t] 表示从 (0, 0) 最多传送 t 次到达 (i - 1, j - 1) 的最小成本。如果不传送,dp[i][j][t] = min(dp[i - 1][j][t], dp[i][j - 1][t]) + grid[i - 1][j - 1],如果传送,需要找到所有元素值大于等于 grid[i - 1][j - 1] 的单元格 (x, y),取 dp[x][y][t - 1] 的最小值。

代码


/**
 * @date 2026-01-28 10:04
 */
public class MinCost3651 {

    public int minCost(int[][] grid, int k) {
        int m = grid.length;
        int n = grid[0].length;
        int[][][] dp = new int[m + 1][n + 1][k + 1];
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                Arrays.fill(dp[i][j], Integer.MAX_VALUE / 2);
            }
        }
        int maxCost = 0;
        for (int[] row : grid) {
            for (int cost : row) {
                maxCost = Math.max(maxCost, cost);
            }
        }
        int[] min = new int[maxCost + 1];
        Arrays.fill(min, Integer.MAX_VALUE);
        int[] suffixMin = new int[maxCost + 2];
        Arrays.fill(suffixMin, Integer.MAX_VALUE);
        for (int t = 0; t <= k; t++) {
            dp[0][1][t] = -grid[0][0];
            dp[1][0][t] = -grid[0][0];
            for (int i = 1; i <= m; i++) {
                for (int j = 1; j <= n; j++) {
                    int cost = grid[i - 1][j - 1];
                    dp[i][j][t] = Math.min(Math.min(dp[i - 1][j][t], dp[i][j - 1][t]) + cost, suffixMin[cost]);
                    min[cost] = Math.min(min[cost], dp[i][j][t]);
                }
            }

            for (int i = maxCost; i >= 0; i--) {
                suffixMin[i] = Math.min(suffixMin[i + 1], min[i]);
            }
        }

        return dp[m][n][k];
    }

}

性能

3510.移除最小数对使数组有序II

目标

给你一个数组 nums,你可以执行以下操作任意次数:

  • 选择 相邻 元素对中 和最小 的一对。如果存在多个这样的对,选择最左边的一个。
  • 用它们的和替换这对元素。

返回将数组变为 非递减 所需的 最小操作次数 。

如果一个数组中每个元素都大于或等于它前一个元素(如果存在的话),则称该数组为非递减。

示例 1:

输入: nums = [5,2,3,1]
输出: 2
解释:
元素对 (3,1) 的和最小,为 4。替换后 nums = [5,2,4]。
元素对 (2,4) 的和为 6。替换后 nums = [5,6]。
数组 nums 在两次操作后变为非递减。

示例 2:

输入: nums = [1,2,2]
输出: 0
解释:
数组 nums 已经是非递减的。

说明:

  • 1 <= nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9

提示:

  • We can perform the simulation using data structures.
  • Maintain an array index and value using a map since we need to find the next and previous ones.
  • Maintain the indices to be removed using a hash set.
  • Maintain the neighbor sums with the smaller indices (set or priority queue).
  • Keep the 3 structures in sync during the removals.

思路

代码

性能

3454.分割正方形II

目标

给你一个二维整数数组 squares ,其中 squares[i] = [xi, yi, li] 表示一个与 x 轴平行的正方形的左下角坐标和正方形的边长。

找到一个最小的 y 坐标,它对应一条水平线,该线需要满足它以上正方形的总面积 等于 该线以下正方形的总面积。

答案如果与实际答案的误差在 10^-5 以内,将视为正确答案。

注意:正方形 可能会 重叠。重叠区域只 统计一次 。

示例 1:

输入: squares = [[0,0,1],[2,2,1]]
输出: 1.00000
解释:
任何在 y = 1 和 y = 2 之间的水平线都会有 1 平方单位的面积在其上方,1 平方单位的面积在其下方。最小的 y 坐标是 1。

示例 2:

输入: squares = [[0,0,2],[1,1,1]]
输出: 1.00000
解释:
由于蓝色正方形和红色正方形有重叠区域且重叠区域只统计一次。所以直线 y = 1 将正方形分割成两部分且面积相等。

说明:

  • 1 <= squares.length <= 5 * 10^4
  • squares[i] = [xi, yi, li]
  • squares[i].length == 3
  • 0 <= xi, yi <= 10^9
  • 1 <= li <= 10^
  • 所有正方形的总面积不超过 10^15。

思路

代码

性能

85.最大矩形

目标

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

示例 2:

输入:matrix = [["0"]]
输出:0

示例 3:

输入:matrix = [["1"]]
输出:1

说明:

  • rows == matrix.length
  • cols == matrix[0].length
  • 1 <= rows, cols <= 200
  • matrix[i][j] 为 '0' 或 '1'

思路

代码

性能

1458.两个子序列的最大点积

目标

给你两个数组 nums1 和 nums2 。

请你返回 nums1 和 nums2 中两个长度相同的 非空 子序列的最大点积。

数组的非空子序列是通过删除原数组中某些元素(可能一个也不删除)后剩余数字组成的序列,但不能改变数字间相对顺序。比方说,[2,3,5] 是 [1,2,3,4,5] 的一个子序列而 [1,5,3] 不是。

示例 1:

输入:nums1 = [2,1,-2,5], nums2 = [3,0,-6]
输出:18
解释:从 nums1 中得到子序列 [2,-2] ,从 nums2 中得到子序列 [3,-6] 。
它们的点积为 (2*3 + (-2)*(-6)) = 18 。

示例 2:

输入:nums1 = [3,-2], nums2 = [2,-6,7]
输出:21
解释:从 nums1 中得到子序列 [3] ,从 nums2 中得到子序列 [7] 。
它们的点积为 (3*7) = 21 。

示例 3:

输入:nums1 = [-1,-1], nums2 = [1,1]
输出:-1
解释:从 nums1 中得到子序列 [-1] ,从 nums2 中得到子序列 [1] 。
它们的点积为 -1 。

说明:

  • 1 <= nums1.length, nums2.length <= 500
  • -1000 <= nums1[i], nums2[i] <= 1000

思路

有两个数组 nums1nums2,求这两个数组长度相等的子序列的点积的最大值。

定义 dp[i][j] 表示 nums1 的前 i 个元素的子序列与 nums2 的前 j 个元素的子序列的最大点积

  • 如果选择 nums[i] * nums[j],剩下的子问题变成 nums1 的前 i - 1 个元素的子序列 与 nums2 的前 j - 1 个元素的子序列的点积最大值,或者为 0,因为当前已经选择了,前面可以不选。即 Math.max(0, dp[i - 1][j - 1]) + nums[i] * nums[j]
  • 如果不选 nums[i] * nums[j],问题变成 nums1 的前 i - 1 个元素的子序列 与 nums2 的前 j 个元素的子序列的点积最大值 dp[i - 1][j],以及 dp[i][j - 1]dp[i - 1][j - 1]

代码


/**
 * @date 2026-01-08 9:05
 */
public class MaxDotProduct1458 {

    public int maxDotProduct(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        int[][] dp = new int[n1 + 1][n2 + 1];
        Arrays.fill(dp[0], Integer.MIN_VALUE);
        for (int i = 0; i <= n1; i++) {
            dp[i][0] = Integer.MIN_VALUE;
        }
        for (int i = 1; i <= n1; i++) {
            for (int j = 1; j <= n2; j++) {
                dp[i][j] = Math.max(Math.max(0, dp[i - 1][j - 1]) + nums1[i - 1] * nums2[j - 1], Math.max(dp[i - 1][j], dp[i][j - 1]));
            }
        }
        return dp[n1][n2];
    }
}

性能

1411.给Nx3网格图涂色的方案数

目标

你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同)。

给你网格图的行数 n 。

请你返回给 grid 涂色的方案数。由于答案可能会非常大,请你返回答案对 10^9 + 7 取余的结果。

示例 1:

输入:n = 1
输出:12
解释:总共有 12 种可行的方法:

示例 2:

输入:n = 2
输出:54

示例 3:

输入:n = 3
输出:246

示例 4:

输入:n = 7
输出:106494

示例 5:

输入:n = 5000
输出:30228214

说明:

  • n == grid.length
  • grid[i].length == 3
  • 1 <= n <= 5000

思路

代码

性能

1970.你能穿过矩阵的最后一天

目标

给你一个下标从 1 开始的二进制矩阵,其中 0 表示陆地,1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。

一开始在第 0 天,整个 矩阵都是 陆地 。但每一天都会有一块新陆地被 水 淹没变成水域。给你一个下标从 1 开始的二维数组 cells ,其中 cells[i] = [ri, ci] 表示在第 i 天,第 ri 行 ci 列(下标都是从 1 开始)的陆地会变成 水域 (也就是 0 变成 1 )。

你想知道从矩阵最 上面 一行走到最 下面 一行,且只经过陆地格子的 最后一天 是哪一天。你可以从最上面一行的 任意 格子出发,到达最下面一行的 任意 格子。你只能沿着 四个 基本方向移动(也就是上下左右)。

请返回只经过陆地格子能从最 上面 一行走到最 下面 一行的 最后一天 。

示例 1:

输入:row = 2, col = 2, cells = [[1,1],[2,1],[1,2],[2,2]]
输出:2
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 2 天。

示例 2:

输入:row = 2, col = 2, cells = [[1,1],[1,2],[2,1],[2,2]]
输出:1
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 1 天。

示例 3:

输入:row = 3, col = 3, cells = [[1,2],[2,1],[3,3],[2,2],[1,1],[1,3],[2,3],[3,2],[3,1]]
输出:3
解释:上图描述了矩阵从第 0 天开始是如何变化的。
可以从最上面一行到最下面一行的最后一天是第 3 天。

说明:

  • 2 <= row, col <= 2 * 10^4
  • 4 <= row col <= 2 10^4
  • cells.length == row * col
  • 1 <= ri <= row
  • 1 <= ci <= col
  • cells 中的所有格子坐标都是 唯一 的。

思路

有一个二进制矩阵,0 代表陆地,1 代表水域。第 0 天,整个矩阵都是陆地,之后的每一天都会有一块陆地变为水域,cells[i] = [rowi, coli] 表示第 i + 1 天,矩阵的 rowi 行,coli 列会变为水域,注意行列的下标从 1 开始。返回能从第一行走到最后一行的最后一天是哪天。

BFS 可用于判断路径是否存在,二分答案判断即可。

代码


/**
 * @date 2025-12-31 9:56
 */
public class LatestDayToCross1970 {

    public int latestDayToCross(int row, int col, int[][] cells) {
        int l = 0, r = cells.length - 1;
        int m = l + (r - l) / 2;
        while (l <= r) {
            if (check(row, col, m, cells)) {
                l = m + 1;
            } else {
                r = m - 1;
            }
            m = l + (r - l) / 2;
        }
        return r;
    }

    public int[][] directions = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public boolean check(int row, int col, int m, int[][] cells) {
        int[][] grid = new int[row + 1][col + 1];
        for (int i = 0; i < m; i++) {
            grid[cells[i][0]][cells[i][1]] = 1;
        }
        Deque<int[]> q = new ArrayDeque<>();
        for (int i = 1; i <= col; i++) {
            if (grid[1][i] == 0) {
                grid[1][i] = 1;
                q.offer(new int[]{1, i});
            }
        }
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] cur = q.poll();
                for (int[] direction : directions) {
                    int x = cur[0] + direction[0];
                    int y = cur[1] + direction[1];
                    if (x >= 1 && x <= row && y >= 1 && y <= col && grid[x][y] == 0) {
                        if (x == row) {
                            return true;
                        }
                        grid[x][y] = 1;
                        q.offer(new int[]{x, y});
                    }
                }
            }
        }
        return false;
    }

}

性能