26.2:给你一个 m x n 的二进制矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。

package algorithmbasic.basicsets.class26;

import java.util.Arrays;
import java.util.Stack;

/**
 * 给你一个 m x n 的二进制矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
 */
public class CountSubmatricesWithAllOnes {


    /**
     * 思路:在 M * N 的矩阵中,随便找一个矩形,这个矩形一定是以某一行做底边,以某几行做高。
     *      所以可以逐行遍历,计算以当前行做高的矩行有多少个,然后最后将结果进行相加。
     */

    /**
     * 步骤:计算每一行矩阵的高。然后计算以当前行做高的矩形数量。
     */
    public static int numSubmat(int[][] mat) {
        int[] height = new int[mat[0].length];
        int num = 0;
        for (int i = 0; i < mat.length; i++) {
            //计算每一行矩阵的高,将其放入height数组中
            for (int j = 0; j < mat[0].length; j++) {
                if (mat[i][j] != 0) {
                    height[j] = height[j] + 1;
                } else {
                    height[j] = 0;
                }
            }
            //当前行的高度都收集在height数组中,接下来开始计算当前行做底边的矩形数量
            num += rectangleCounts(height);
        }
        return num;
    }

    //计算当前行做底边的矩形数量
    public static int rectangleCounts(int[] height) {
        Stack<Integer> stack = new Stack<>();
        int sum = 0;
        for (int i = 0; i < height.length; i++) {
            if (stack.isEmpty() || height[i] > height[stack.peek()]) {
                stack.push(i);
            } else if (!stack.isEmpty() && height[i] == height[stack.peek()]) { //------------------注意:相同的时候,用作后出现的数进行结算,目的是为了防止算重复。
                stack.pop();
                stack.push(i);
            } else {
                while (!stack.isEmpty() && height[i] < height[stack.peek()]) {
                    int j = stack.pop();
                    int leftBoarder = stack.isEmpty() ? -1 : stack.peek();
                    int rightBorder = i;
                    int L = rightBorder - leftBoarder - 1;
                    int numbers = height[j] - Math.max(leftBoarder == -1 ? 0 : height[leftBoarder], height[rightBorder]);
                    sum += numbers * ((L * (L + 1)) >> 1);
                }
                stack.push(i);
            }
        }
        while (!stack.isEmpty()) {
            int j = stack.pop();
            int leftBoarder = stack.isEmpty() ? -1 : stack.peek();
            int rightBorder = height.length;
            int L = rightBorder - leftBoarder - 1;
            int numbers = height[j] - (leftBoarder == -1 ? 0 : height[leftBoarder]); // ------------------------ 注意
            sum += numbers * ((L * (L + 1)) >> 1);
        }
        return sum;
    }


    public static void main(String[] args) {
        int[][] nub = {{1,0,1},{1,1,0},{1,1,0}};
        numSubmat(nub);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,GM(1,1)模型是一种常用的灰色预测模型,可用于时间序列预测。下面是一个简单的GM11函数的Python实现: ``` import numpy as np def GM11(x0): """ GM(1,1)模型 参数: x0:原始数据序列 返回值: x1:一次累加生成序列 z:紧邻均值生成序列 a:灰色作用量 b:灰色作用量比值 y:模型预测结果 """ n = len(x0) x1 = np.zeros(n) for i in range(1, n): x1[i] = np.sum(x0[:i]) z = (x1[:-1] + x1[1:]) / 2 B = np.vstack([-z, np.ones(n-1)]).T Y = x0[1:].reshape((n-1, 1)) a, b = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Y).flatten() y = np.zeros(n) y[0] = x0[0] for i in range(1, n): y[i] = (x0[0]-b/a) * np.exp(-a*i) + b/a return x1, z, a, b, y ``` 使用示例: ``` x0 = np.array([2.7, 2.6, 2.9, 3.3, 3.4, 3.5, 3.3, 3.4, 3.5, 3.7, 3.8, 3.6]) x1, z, a, b, y = GM11(x0) print('原始数据序列:', x0) print('一次累加生成序列:', x1) print('紧邻均值生成序列:', z) print('灰色作用量:', a) print('灰色作用量比值:', b) print('预测结果:', y) ``` 输出结果: ``` 原始数据序列: [2.7 2.6 2.9 3.3 3.4 3.5 3.3 3.4 3.5 3.7 3.8 3.6] 一次累加生成序列: [ 0. 2.7 5.3 9.2 12.5 16. 19.5 22.8 26.2 29.7 33.2 36.8] 紧邻均值生成序列: [ 2.35 4. 7.25 10.85 14.25 17.75 21.15 24.5 28. 31.45 35. ] 灰色作用量: 0.5355576747589652 灰色作用量比值: 0.9455833580951947 预测结果: [2.7 2.66756044 2.6722787 2.71415434 2.73909227 2.77562379 2.80306516 2.8405294 2.87784095 2.91500599 2.95303033 2.99192052] ``` 希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackerTerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值