(2/60)有序数组平方、长度最小子数组、螺旋矩阵

有序数组的平方

leetcode:977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

暴力法

思路

  1. 遍历数组,元素原地替换为自身平方值。
  2. 将数组进行排序。

复杂度分析

时间复杂度:O(N+logN)

空间复杂度:O(1)

注意点

  1. sort(parm1,parm2,options),接收首地址/迭代器、末地址/迭代器、比较函数。
  2. begin()、end()方法返回首、末迭代器。c++里很多容器都有这两个方法。

代码实现

class Solution {
public:
// 暴力法,先平方再排序
vector<int> sortedSquares(vector<int>& nums) {
for(int i = 0;i < nums.size();i++){
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};

相向双指针法

思路

基于1. 原数组有序;2. 元素有正有负两条特性,元素平方后的值,最大值一定出现在两端,利用相向双指针从两端向中间靠拢,寻找每一轮的最大值,倒序赋值给新数组,从而达到排序效果。

  1. 初始化左、右指针、新数组、新数组指针(末位) .

  2. 左右指针对比,找到本轮自身平方最大的元素,填入新数组中。

    若左元素大,则填入左元素,left++,cur--;

    否则,填入右元素,right--,cur--;

  3. 重复2直至left>right,循环结束。

复杂度分析

时间复杂度:O(N)

空间复杂度:O(N),额外开辟了一个等大数组.

注意点

  1. 必须在新开辟数组填入元素,否则修改原数组会污染数据.

代码实现

class Solution {
public:
// 相向双指针,利用最大值出现在数组两端的特性(有正有负)
// 两指针向中间靠拢,每次都找到剩余元素中最大的,
// 将找到的元素倒序插入新数组中,即可完成排序
vector<int> sortedSquares(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
int cur = nums.size() - 1;
vector<int> arr(nums.size());
// 右闭原则
while(left <= right){
// 每轮取最大的元素,倒序填入
if(nums[left]*nums[left] > nums[right]*nums[right]){ // left大
arr[cur--] = nums[left]*nums[left];
left++;
}else{ // right大或相等
arr[cur--] = nums[right]*nums[right];
right--;
}
}
return arr;
}
};

长度最小的子数组

leetcode:209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0

暴力法

思路

外层代表终止指针,遍历数组;内层代表起始指针,从0遍历到终止指针。内层遍历过程中起始指针不断后移,同时不断检测是否还满足条件。

  1. 外层循环,移动终止指针i,遍历数组
  2. 内层循环,移动起始指针j,遍历0~i(含i),如果局部和curSum >= target那么就尝试更新(与历史最短比较,如果更短就更新数值)最短值。
  3. 重复2直至遍历完成,返回时检测result是否更新过,若未更新则不存在满足条件的子序列,返回0。

复杂度分析

时间复杂度:O(N)

空间复杂度:O(1)

注意点

  1. 内层循环要使用局部累和curSum,否则用原累和sum会污染数据。
  2. 内层j可以取到i,此时长度为1。

代码实现

class Solution {
public:
// 暴力法
// 外层终止指针遍历数组
// 内层起始指针遍历到终止指针,找到最小值
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0;
for(int i = 0;i < nums.size();i++){
sum += nums[i];
if(sum >= target){
int curSum = sum;
for(int j = 0;j <= i; ){
if(curSum >= target){
// 尝试更新
int subLength = i-j+1;
result = subLength < result ? subLength : result;
curSum -= nums[j++];
}else{
break;
}
}
}
}
return result == INT32_MAX ? 0 : result;
}
};

滑动窗口法(同向双指针)

思路

设置同向双指针,利用nums元素是正数的特点,终止指针后移一定使累和增大,起始指针后移一定使累和减小,不存在起始指针回头还是最优解的情况。

  1. 外层循环移动终止指针i,遍历数组,同时计算累和sum
  2. sum >= target时,内层循环移动起始指针j,尝试更新最短长度。
  3. 重复1、2,直至循环完毕。返回时检测result是否更新过,若未更新则不存在满足条件的子序列,返回0。

复杂度分析

时间复杂度:O(N)。虽然两层循环,但i、j整体只会移动N次

空间复杂度:O(1)。无额外空间。

注意点

  1. 内层j可以取到i,此时长度为1。

代码实现

class Solution {
public:
// 滑动窗口(同向双指针)
// 因为nums元素都是正数,终止指针后移累和一定增大
// 起始指针后移累和一定减小,不存在起始指针回头还满足条件的情况
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0;
// 外层移动终止指针
for(int i = 0,j = 0;i < nums.size();i++){
sum += nums[i];
while(sum >= target && j <= i){
int subLength = i-j+1;
result = subLength < result ? subLength : result;
sum -= nums[j++];
}
}
return result == INT32_MAX ? 0 : result;
}
};

螺旋矩阵

思路

表现是螺旋形,但是处理时是一环一环地处理。

  1. 声明一个大小为n×n的二维矩阵matrix,并将每个元素初始化为n×n(避免了处理N为奇数的情况)。
  2. 进入循环,循环条件为需要进行的螺旋层数loop大于等于0。
  3. 在每一层中,按照螺旋顺序遍历矩阵的边界,将计数器count的值逐个赋给矩阵对应位置的元素,并将count加1。
  4. 每完成一次螺旋遍历,需要进行的螺旋层数loop减1,同时记录当前层的偏移量offset加1。
  5. 循环结束后,返回生成的螺旋矩阵matrix。

复杂度分析

时间复杂度:O(N^2)。

空间复杂度:O(N^2)。额外声明了二维数组。

注意点

  1. 左闭右开原则,每次只处理到末元素前一个。
  2. 元素初始化为N*N,避免了N是奇数时的处理。

代码实现

class Solution {
public:
// 左闭右开原则
vector<vector<int>> generateMatrix(int n) {
int count = 1;
int loop = n/2;
int offset = 0;
int i=0,j=0;
// 声明n*n矩阵,元素初始化为n*n
vector<vector<int>> matrix(n,vector<int>(n,n*n));
while(loop--){
for(j = offset;j < n - 1 - offset;j++){
matrix[offset][j] = count++;
}
for(i = offset;i < n - 1 - offset;i++){
matrix[i][j] = count++;
}
for(;j > offset;j--){
matrix[i][j] = count++;
}
for(;i > offset;i--){
matrix[i][j] = count++;
}
offset++;
}
return matrix;
}
};
posted @   Tazdingo  阅读(2380)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示