欢迎大家加QQ群:623375442,可以方便群里面交流。

100286. Make a Square with the Same Color

给你一个二维 3 x 3 的矩阵 grid ,每个格子都是一个字符,要么是 'B' ,要么是 'W' 。字符 'W' 表示白色,字符 'B' 表示黑色。

你的任务是改变 至多一个 格子的颜色,使得矩阵中存在一个 2 x 2 颜色完全相同的正方形。

如果可以得到一个相同颜色的 2 x 2 正方形,那么返回 true ,否则返回 false 。

测试样例:

输入:grid = [["B","W","B"],["B","W","W"],["B","W","B"]]

输出:true

解释:修改 grid[0][2] 的颜色,可以满足要求。

解答:暴力。

class Solution {
    public boolean canMakeSquare(char[][] grid) {
        for (int i = 1; i < 3; ++i) {
            for (int j = 1; j < 3; ++j) {
                int b = 0, w = 0;
                for (int d1 = -1; d1 <= 0; ++d1) {
                    for (int d2 = -1; d2 <= 0; ++d2) {
                        if (grid[i + d1][j + d2] == 'B') {
                            ++b;
                        } else {
                            ++w;
                        }
                    }
                }
                if (b <= 1 || w <= 1) {
                    return true;
                }
            }
        }
        return false;
    }
}

100278. Right Triangles

给你一个二维 boolean 矩阵 grid 。

请你返回使用 grid 中的 3 个元素可以构建的 直角三角形 数目,且满足 3 个元素值 都 为 1 。

注意:

  • 如果 grid 中 3 个元素满足:一个元素与另一个元素在 同一行,同时与第三个元素在 同一列 ,那么这 3 个元素称为一个 直角三角形 。这 3 个元素互相之间不需要相邻。

测试样例:

输入:grid = [[0,1,0],[0,1,1],[0,1,0]]

输出:2

解释:有 2 个直角三角形。

解答:利用乘法配合计数。

class Solution {
    public long numberOfRightTriangles(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[] row = new int[m], col = new int[n];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                row[i] += grid[i][j];
                col[j] += grid[i][j];
            }
        }

        long res = 0;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1) {
                    long r = row[i] - 1L, c = col[j] - 1L;
                    // 满足要求的直角数量 = 当前列可选点 * 当前行可选点
                    // 可选 = 除去当前点之外的所有点都满足要求
                    res += r * c;
                }
            }
        }
        return res;
    }
}

100293. Find All Possible Stable Binary Arrays II

给你 3 个正整数 zero ,one 和 limit 。

一个 二进制数组 arr 如果满足以下条件,那么我们称它是 稳定的 :

  • 0 在 arr 中出现次数 恰好 为 zero 。
  • 1 在 arr 中出现次数 恰好 为 one 。
  • arr 中每个长度超过 limit 的 子数组 都 同时 包含 0 和 1 。

请你返回 稳定 二进制数组的 总 数目。

由于答案可能很大,将它对 10^9 + 7 取余 后返回。

测试样例:

输入:zero = 1, one = 1, limit = 2

输出:2

解释:两个稳定的二进制数组为 [1,0] 和 [0,1] ,两个数组都有一个 0 和一个 1 ,且没有子数组长度大于 2 。

解答:可以用动态规划。不能连续出现limit + 1的0或者1,同时0和1总出现次数也有限制。可以利用链表来转移矩阵(暴力遍历复杂度会爆炸)。

class Solution {
    private static final int mod = 1_000_000_007;

    public int numberOfStableArrays(int zero, int one, int limit) {
        LinkedList<Integer>[] zeros = new LinkedList[zero + 1], ones = new LinkedList[one + 1];
        for (int i = 0; i <= zero; ++i) {
            zeros[i] = new LinkedList<>();
        }
        for (int i = 0; i <= one; ++i) {
            ones[i] = new LinkedList<>();
        }
        int[] zeroSum = new int[zero + 1], oneSum = new int[one + 1];

        zeros[zero - 1].add(1);
        zeroSum[zero - 1] = 1;

        ones[one - 1].add(1);
        oneSum[one - 1] = 1;

        for (int i = 2; i <= zero + one; ++i) {
            int[] nextZeroSum = new int[zero + 1], nextOneSum = new int[one + 1];
            for (int j = 0; j < zero; ++j) {
                int used = zero - j;
                // 首先判断是否满足要求:1. 期望使用的个数不能大于总个数 2. 当前的选择不能使另一个数字超过使用上限
                if (used > i) {
                    nextZeroSum[j] = 0;
                    zeros[j] = new LinkedList<>();
                } else if (one - (i - used) < 0) {
                    nextZeroSum[j] = 0;
                    zeros[j] = new LinkedList<>();
                } else {
                    // 位移运算,因为连续增加,可以认为把上一个队列移过来
                    zeros[j] = zeros[j + 1];
                    // 前缀和来加速计算
                    nextZeroSum[j] = zeroSum[j + 1];
                    if (zeros[j].size() == limit) {
                        nextZeroSum[j] = sub(nextZeroSum[j], zeros[j].removeLast());
                    }

                    // 1个连续,可以认为从另一个数字那边增加一个当前数,租借过来。
                    nextZeroSum[j] = add(nextZeroSum[j], oneSum[one - (i - used)]);
                    zeros[j].addFirst(oneSum[one - (i - used)]);
                }
            }
            zeros[zero] = new LinkedList<>();

            for (int j = 0; j < one; ++j) {
                int used = one - j;
                if (used > i) {
                    nextOneSum[j] = 0;
                    ones[j] = new LinkedList<>();
                } else if (zero - (i - used) < 0) {
                    nextOneSum[j] = 0;
                    ones[j] = new LinkedList<>();
                } else {
                    ones[j] = ones[j + 1];
                    nextOneSum[j] = oneSum[j + 1];
                    if (ones[j].size() == limit) {
                        nextOneSum[j] = sub(nextOneSum[j], ones[j].removeLast());
                    }

                    nextOneSum[j] = add(nextOneSum[j], zeroSum[zero - (i - used)]);
                    ones[j].addFirst(zeroSum[zero - (i - used)]);
                }
            }
            ones[one] = new LinkedList<>();

            zeroSum = nextZeroSum;
            oneSum = nextOneSum;
        }

        int res = 0;
        for (int n : zeroSum) {
            res = add(n, res);
        }
        for (int n : oneSum) {
            res = add(n, res);
        }
        return (zeroSum[0] + oneSum[0]) % mod;
    }

    private int sub(int x, int y) {
        return (x - y + mod) % mod;
    }

    private int add(int x, int y) {
        return (x + y) % mod;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *