209.长度最小的子数组
滑动窗口也可以理解为双指针法的一种,只不过这种解法更像是一个窗口的移动
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int sum = 0;
int subLength = 0;
int i = 0;
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
while (sum >= target) {
subLength = j - i + 1;
result = subLength < result ? subLength : result;
sum -= nums[i++];
}
}
return result == INT_MAX ? 0 : result;
}
};
每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。
三元运算符 条件表达式1 ? 表达式2 : 表达式3; 可以用来简化if语句
INT_MAX
59.螺旋矩阵II
模拟过程比较复杂
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int t = 0; // top
int b = n-1; // bottom
int l = 0; // left
int r = n-1; // right
vector<vector<int>> ans(n,vector<int>(n));
int k=1;
while(k<=n*n){
for(int i=l;i<=r;++i,++k) ans[t][i] = k;
++t;
for(int i=t;i<=b;++i,++k) ans[i][r] = k;
--r;
for(int i=r;i>=l;--i,++k) ans[b][i] = k;
--b;
for(int i=b;i>=t;--i,++k) ans[i][l] = k;
++l;
}
return ans;
}
};
跟二分法相同都要遵循,循环不变量的原则
每层更 新 t b l r这几个边界值
区间和
通过前缀和数组的构建,程序能够高效地计算任意区间子数组的和,从而避免了多次重复求和的操作,提高了效率。前缀和在涉及计算区间和的问题时非常有用
ACM输入输出模式
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &vec[i]);
presum += vec[i];
p[i] = presum;
}
while (~scanf("%d%d", &a, &b)) {
int sum;
if (a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
printf("%d\n", sum);
}
}
C++ 代码 面对大量数据 读取 输出操作,最好用scanf 和 printf,耗时会小很多
scanf
函数返回成功读取的输入项的数量,通常是一个正整数。如果读取失败(如到达输入的末尾或输入不符合预期),则返回 EOF
,即 -1
。~
是按位取反运算符。按位取反操作会将一个整数的所有位进行反转。例如,~(-1)
会得到 0
,因为 -1
的二进制表示是所有位都是 1
,取反后变为所有位都是 0
,即 0
。
44. 开发商购买土地
ACM模式,没什么思路
利用前缀和,将各行和各列的和算出来
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
int sum = 0;
vector<vector<int>> vec(n, vector<int>(m, 0)) ;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> vec[i][j];
sum += vec[i][j];
}
}
// 统计横向
vector<int> horizontal(n, 0);
for (int i = 0; i < n; i++) {
for (int j = 0 ; j < m; j++) {
horizontal[i] += vec[i][j];
}
}
// 统计纵向
vector<int> vertical(m , 0);
for (int j = 0; j < m; j++) {
for (int i = 0 ; i < n; i++) {
vertical[j] += vec[i][j];
}
}
int result = INT_MAX;
int horizontalCut = 0;
for (int i = 0 ; i < n; i++) {
horizontalCut += horizontal[i];
result = min(result, abs(sum - horizontalCut - horizontalCut));
}
int verticalCut = 0;
for (int j = 0; j < m; j++) {
verticalCut += vertical[j];
result = min(result, abs(sum - verticalCut - verticalCut));
}
cout << result << endl;
}
abs是取绝对值