Day 2:数组02
1.长度最小的子数组
leetcode:209. 长度最小的子数组 - 力扣(LeetCode)
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm> // 包含 sort 函数所在的头文件
using namespace std;
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left=0, right=0;
int reslen = 0;
//用于计算滑动窗口内的数组和
int sum=0;
if(nums.size()>0){
sum += nums[right];
} else {
return 0;
}
while(left<nums.size()){
if(sum >= target){
int lentemp = right-left+1;
if(reslen == 0){
reslen = lentemp;
} else {
reslen = lentemp<reslen ? lentemp : reslen;
}
sum -= nums[left];
left++;
} else {
if(right<nums.size()-1){
right++;
} else {
//这里应该有两种情况:
//1:r到头了没找到,那就返回res初始值0
//2:l右移没找到更合适的,那就返回res
return reslen;
}
sum += nums[right];
}
}
return reslen;
}
};
int main(int argc, char *argv[])
{
vector<int> _nums;
int _num;
int _target;
while(cin>>_num){
_nums.push_back(_num);
if(cin.get() == '\n'){
break;
}
}
cin>>_target;
Solution solution;
int ret = solution.minSubArrayLen(_target, _nums);
cout<<ret<<endl;
// for(auto a :ret){
// cout<<a<<" ";
// }
return 0;
}
这里用到的就是滑动窗口,这里的写法比较复杂,下面是代码随想录的解法:
他是用的一个for循环内嵌while,而且对于最终数组长度reslen的初始化更加便捷,直接赋值INT32_MAX,最后判断的时候也是,直接判断这个值是否有改变就可以
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
作者:代码随想录
链接:https://leetcode.cn/problems/minimum-size-subarray-sum/solutions/1706223/by-carlsun-2-iiee/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
附加题目
leetcode:904. 水果成篮 - 力扣(LeetCode)
待
leetcode:76. 最小覆盖子串 - 力扣(LeetCode)
待
2.螺旋矩阵II
leetcode:59. 螺旋矩阵 II - 力扣(LeetCode)
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n, vector<int>(n,0));
int loop = n/2;
int startx=0, starty=0;
int offset = 1;
int count = 1;
while(loop--){
int i = starty;
int j = startx;
//上
for(j; j<n-offset; j++){
result[i][j] = count++;
}
//右
for(i; i<n-offset; i++){
result[i][j] = count++;
}
//下
for(; j>startx; j--){
result[i][j] = count++;
}
//左
for(; i>starty; i--){
result[i][j] = count++;
}
offset++;
startx++;
starty++;
}
if(n%2 == 1){
result[n/2][n/2] = n*n;
}
return result;
}
};
int main(int argc, char *argv[])
{
int _target;
cin>>_target;
Solution solution;
vector<vector<int>> ret = solution.generateMatrix(_target);
for(auto a :ret){
for(auto b :a){
cout<<b<<" ";
}
cout<<endl;
}
return 0;
}
这个题比较绕,主要的结题思路就是复杂问题简单化,一圈一圈的去处理问题
每一圈都是画四条边:上、右、下、左
每一条边都是按照左闭右开的区间画
几个变量:loop圈数、(startx,starty)是每一圈的起始坐标点、offset是每一圈的偏移量,由于确定“右开”的坐标点
再一个要注意的点就是,二维数组和xy坐标是不一样的!!!
xy坐标向右是x++,而[i,j]二维数组向右是j++!
3.区间和
kamacoder:44. 开发商购买土地(第五期模拟笔试)
先看一下前缀题目:
kamacoder:58. 区间和(第九期模拟笔试)
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
int n;
cin>>n;
vector<int> array;
while(n--){
int num;
cin>>num;
array.push_back(num);
}
//区间和
vector<int> sum_array(array.size(), 0);
int sum=0;
for(int i=0; i<array.size(); i++){
sum += array[i];
sum_array[i] = sum;
}
int a,b;
while(cin>>a>>b){
int res=0;
if(a==0){
res = sum_array[b];
} else {
res = sum_array[b] - sum_array[a-1];
}
cout<<res<<endl;
}
return 0;
}
数组区间和其实就是:先创建一个等长数组,然后每一位存储0到该位的累计和,算区间和的时候呢,输入[a,b],如果a=0,就返回sum_array[b],否则就返回sum_array[b]-sum_array[a]。
回来看原来的题:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
int n,m;
if (!(cin >> n >> m)) {
cerr << "Failed to read dimensions." << endl;
return 1;
}
vector<vector<int>> array(n, vector<int>(m, 0));
// Read matrix elements into the array.
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (!(cin >> array[i][j])) {
cerr << "Invalid input for matrix element." << endl;
return 1;
}
}
}
//前n行和
vector<int> sum_i(n,0);
int sum =0;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
sum += array[i][j];
}
sum_i[i] = sum;
}
//前m列和
vector<int> sum_j(m,0);
int _sum=0;
for(int j=0; j<m; j++){
for(int i=0; i<n; i++){
_sum += array[i][j];
}
sum_j[j] = _sum;
}
int res = INT32_MAX;
//所有数的总和
int all_sum = sum_i[n-1];
//按照行来遍历
for(int _n=0; _n<n; _n++){
int cut_i = abs(all_sum - sum_i[_n] - sum_i[_n]);
res = cut_i<res ? cut_i : res;
}
//按照列来遍历
for(int _m=0; _m<m; _m++){
int cut_j = abs(all_sum - sum_j[_m] - sum_j[_m]);
res = cut_j<res ? cut_j : res;
}
cout<<res<<endl;
return 0;
}
这个题其实结合上面的题目,解起来还好,主要的问题在于输入部分的处理,我之前的写法是这样的:
int n,m;
cin>>n>>m;
vector<vector<int>> array(n, vector<int>(m, 0));
int num=0;
vector<int> vec;
while(cin>>num){
vec.push_back(num);
if(cin.get() == '\n'){
array.push_back(vec);
vec.clear();
}
if(cin.peek() == '\n'){
array.push_back(vec);
break;
}
}
这样本地测试没有问题,但是提交上去后会提示“存在数组越界的风险”
改成了chatgpt给的写法:
int n, m;
if (!(cin >> n >> m)) {
cerr << "Failed to read dimensions." << endl;
return 1;
}
vector<vector<int>> array(n, vector<int>(m, 0));
// Read matrix elements into the array.
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (!(cin >> array[i][j])) {
cerr << "Invalid input for matrix element." << endl;
return 1;
}
}
}
先定义好二维数组的大小,再依次输入定值。
2142



被折叠的 条评论
为什么被折叠?



