第2天,今天数组加强,加油
—————————————
文章讲解:
代码随想录
因为是平方,所以最大元素在数组两端都有可能出现,利用双指针从两边寻找最大元素开始,到i=j停止
时间复杂度O(n),比暴力解法用快排sort(A.begin() ,B.end()) 的O(n+nlogn)好不少
注意巩固vector容器的基础
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
//定义一个的储存排序后元素的新数组
//注意vector动态数组初始化,vector<数组类型> 数组名 (数组大小,值);
//如vector<int> A (100,0) 即设置大小为100且所有数为0的整型动态数组A
vector<int> result(nums.size(),0);
//因为新数组是从找最大元素开始,所以新数组的下标从最大开始向前移动,这里初始化
int k = nums.size()-1;
//双指针开始遍历,i从左往右由小到j,j从右往左由大到i
for (int i=0,j=nums.size()-1;i<=j;)
{
if(nums[i]*nums[i]>nums[j]*nums[j])
{
result[k--]=nums[i]*nums[i];
i++; //i由小到j
}
else
{
result[k--]=nums[j]*nums[j];
j--; //j由大到i
}
}
return result;
}
};
LeetCode 209.长度最小的子数组
文章讲解:代码随想录
for*for 暴力解法,即利用 i 轮遍历计算每种达到target的组合方式nums[j]+nums[j+1]...中,哪种组合最短,时间复杂度O(n^2)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
//考虑到极限的结果是需要无限多个数的和才能大于等于target,所以初始化result为最大int
int result = INT32_MAX;
//初始化指针,和
int i=0 ,sum=0, sublength=0;
//遍历开始
for (i=0;i<nums.size();i++)
{
sum = 0;
for (int j=i, j<nums.size();j++)
{
sum+=nums[j];
if (sum >= target) { // 发现sum>=target,更新result
sublength = j - i + 1; // 取子序列的长度
result = result < subLength ? result : subLength;
break; // 找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
//判断result是否较于赋值的INT32_MAX有变化
return result == INT32_MAX?0:result;
}
};
双指针滑动窗口解法
思想:用i和j双指针组成类似“窗口”一样的区间,用尽可能小的窗口去切割出区间sum为target,最后返回最小区间长度
多多注意数组长度为下标长度+1
注意先执行取result,再滑动i去缩小窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
//考虑到极限的结果是需要无限多个数的和才能大于等于target,所以初始化result为最大int
int result = INT32_MAX;
//初始化
int i=0 ,j=0 ,sum=0, sublength=0;
//遍历开始
for (j=0;j<nums.size();j++)
{
//j开始向右滑动收集元素
sum+=nums[j];
//如果sum>=target了,就开始右移i指针,缩小窗口范围,以尽可能少元素(短数组)sum成target
while(sum>=target)
{
sublength = j-i+1;
//不断刷新保留最少元素(最短数组)的结果,即用尽可能小的窗口去切割出target
result = min(result,sublength);
sum=sum-nums[i];
i++;
}
}
//判断result是否较于赋值的INT32_MAX有变化
return result == INT32_MAX?0:result;
}
};
LeetCode 59.螺旋矩阵II
文章讲解:代码随想录
方法一:画完一圈缩边界
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
int offset=1;
int startx;
int starty;
int val=1;
int loop = n/2;
int mid = n/2;
while(loop--)
{
int i=startx;
int j=starty;
//从左上往右上
for(j;j<n-offset;j++){
res[i][j]=val++;
}
//从右上到右下
for(i;i<n-offset;i++){
res[i][j]=val++;
}
//从右下到左下,这里是++后的j
for(;j>starty;j--){
res[i][j]=val++;
}
//从左下到左上,这里是++后的i
for(;i>startx;i--){
res[i][j]=val++;
}
startx++; //下一圈,起始坐标各加一
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset++;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2) {
res[mid][mid] = val;
}
return res;
}
};
方法二:扫描线,画一边缩一次边界
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int num =1, matrix = n*n; //确认元素区间[num,n*n]
//初始化四面边界
int top = 0;
int bot = n-1;
int left = 0;
int right = n-1;
while(num<=matrix)
{
//矩阵中我们习惯:[行][列]
//固定top,用left当扫描线向right扫描并逐个填入[列]
for (int i = left; i <= right; i++) res[top][i]=num++;
//上界下缩
top++;
//固定right,用top当扫描线向bot扫描并逐个填入[行]
for (int i = top; i <= bot; i++) res[i][right]=num++;
//右界左缩
right--;
//固定bot,用right当扫描线向left扫描并逐个填入[列]
for (int i = right; i >= left; i--) res[bot][i]=num++;
//下界上缩
bot--;
//固定left,用bot当扫描线向top扫描并逐个填入[行]
for (int i = bot; i>=top; i--) res[i][left]=num++;
//左界右缩
left++;
}
return res;
}
};