7.14 map | 内存 | 二维dp | 二维前缀和
二维前缀和
lc1314.
class Solution {
public:
vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> prefix(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + mat[i-1][j-1];
}
}
vector<vector<int>> ans(m, vector<int>(n, 0));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
// 计算左上角坐标 (row1, col1) 和右下角坐标 (row2, col2)
int row1 = max(i - K, 0), col1 = max(j - K, 0);
int row2 = min(i + K, m - 1), col2 = min(j + K, n - 1);
ans[i][j] = prefix[row2+1][col2+1] - prefix[row2+1][col1] - prefix[row1][col2+1] + prefix[row1][col1];
//默认不包,包要+1
}
}
return ans;
}
};
最优子结构
lc211.最大正方形
图解
判断出最长边
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix)
{
int ret=0;
int m=matrix.size(),n=matrix[0].size();
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i=0;i<m;i++)
{
dp[i][0]=matrix[i][0]-'0';
ret=max(ret,dp[i][0]);
}
for(int j=0;j<n;j++)
{
dp[0][j]=matrix[0][j]-'0';
ret=max(ret,dp[0][j]);
}
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
if(matrix[i][j]-'0'==1)
dp[i][j]=1+min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]));
ret=max(dp[i][j],ret);
}
}
return ret*ret;
}
};
同类型
lc1277.全一正方形个数
dp[I][j]: 枚举右下角,min(三方位)+1
eg. dp[i][j] = min({dp[i-1][j], dp[i][j-1], dp[i-1][j-1]}) + 1;
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int>> dp(m, vector<int>(n, 0));
int total = 0;
// 初始化第一行和第一列
for (int i = 0; i < m; ++i) {
dp[i][0] = matrix[i][0];
total += dp[i][0];
}
for (int j = 1; j < n; ++j) {
dp[0][j] = matrix[0][j];
total += dp[0][j];
}
// 填充dp数组
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
if (matrix[i][j] == 1) {
dp[i][j] = min({dp[i-1][j], dp[i][j-1], dp[i-1][j-1]}) + 1;
total += dp[i][j];
}
}
}
return total;
}
};
cpp内存
进程地址空间,页表映射和内存对齐。
简单说就是CPU是按块读取的,按照内存对齐规则安排的话,可以让这些变量尽可能安排在一个块中,就容易读取。
也就是说每一次都按块拿,硬件电路实现就简单,效率就高,安排这些地址(虚拟)的工作由编译器完成。
关于内存连续这个说法并不算错误,但不是完整的内存结构(语言层面接触的是虚拟地址)。
map
map是排好序的(像字典),查改慢,红黑树;
unordered_map不排序(像乱堆),查改快,hash表。
lc165.版本号比较
class Solution {
public:
int compareVersion(string version1, string version2)
{
int i = 0, j = 0;
int m = version1.size(), n = version2.size();
while (i < m || j < n) // 循环条件改为处理完任一字符串
{
int p = 0, q = 0; // 初始化为0,处理长度不同的情况
// 提取version1的下一个修订号
while (i < m && version1[i] != '.') {
p = p * 10 + (version1[i] - '0');
i++;
}
// 提取version2的下一个修订号
while (j < n && version2[j] != '.') {
q = q * 10 + (version2[j] - '0');
j++;
}
if (p != q) {
return p > q ? 1 : -1;
}
// 跳过小数点(若存在)
i++;
j++;
}
return 0;
}
};