前言
C++是一种计算机高级程序设计语言,由C语言扩展升级而产生 ,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。
C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。
C++拥有计算机运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。
Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等 。
Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆 于1990 年代初设计,作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言,随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。
Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器码。
2021年10月,语言流行指数的编译器Tiobe将Python加冕为最受欢迎的编程语言,20年来首次将其置于Java、C和JavaScript之上。
描述
给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。
题目数据保证总会存在一个数值和不超过 k 的矩形区域。
示例 1:
输入:matrix = [[1,0,1],[0,-2,3]], k = 2
输出:2
解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。
示例 2:
输入:matrix = [[2,2,-1]], k = 3
输出:3
方法一:有序集合
思路
我们枚举矩形的上下边界,并计算出该边界内每列的元素和,则原问题转换成了如下一维问题:
给定一个整数数组和一个整数 kkk,计算该数组的最大区间和,要求区间和不超过 kkk。
定义长度为 nnn 的数组 aaa 的前缀和
Si={0i=0a0+a1+⋯+ai−11≤i≤nS_i = \begin{cases} 0&i=0\\ a_0+a_1+\cdots+a_{i-1}&1\le i\le n \end{cases} Si={0a0+a1+⋯+ai−1i=01≤i≤n
则区间 [l,r)[l,r)[l,r) 的区间和 al+al+1+⋯+ar−1a_l+a_{l+1}+\cdots+a_{r-1}al+al+1+⋯+ar−1 可以表示为 Sr−SlS_r-S_lSr−Sl。
枚举 rrr,上述问题的约束 Sr−Sl≤kS_r-S_l\le kSr−Sl≤k 可以转换为 Sl≥Sr−kS_l\ge S_r-kSl≥Sr−k。要使 Sr−SlS_r-S_lSr−Sl 尽可能大,则需要寻找最小的满足 Sl≥Sr−kS_l\ge S_r-kSl≥Sr−k 的 SlS_lSl。我们可以在枚举 rrr 的同时维护一个存储 Si (i<r)S_i\ (i<r)Si (i<r) 的有序集合,则可以在 O(logn)O(\log n)O(logn) 的时间内二分找到符合要求的 SlS_lSl。
代码
class Solution {
public int maxSumSubmatrix(int[][] matrix, int k) {
int ans = Integer.MIN_VALUE;
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m; ++i) { // 枚举上边界
int[] sum = new int[n];
for (int j = i; j < m; ++j) { // 枚举下边界
for (int c = 0; c < n; ++c) {
sum[c] += matrix[j][c]; // 更新每列的元素和
}
TreeSet<Integer> sumSet = new TreeSet<Integer>();
sumSet.add(0);
int s = 0;
for (int v : sum) {
s += v;
Integer ceil = sumSet.ceiling(s - k);
if (ceil != null) {
ans = Math.max(ans, s - ceil);
}
sumSet.add(s);
}
}
}
return ans;
}
}