题目链接:977. 有序数组的平方-简单
题目描述:
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
正常解法是平方后直接排序,时间复杂度是 O(n + nlogn)
。
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
因此采用双指针法,这里需要创建一个新的数组,这里不能在原数组上进行交换,因为最大值始终在数组的两端,因此判断哪一端的值更大然后将其填充在新数组的末尾,判断完后对应的指针往中间移动。因为是对两端进行判断,所以使用左右两个指针left
、right
。
代码如下:
//时间复杂度:O(n)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i = 0; i < nums.size(); ++i)
{
nums[i] = nums[i] * nums[i];
}
vector<int> ans(nums.size(), 0);
int left = 0;
int right = nums.size() - 1;
int i = nums.size() - 1;
while(left <= right)
{
if(nums[left] > nums[right])
{
ans[i] = nums[left];
++left;
}
else if(nums[left] <= nums[right])
{
ans[i] = nums[right];
--right;
}
--i;
}
return ans;
}
};
题目链接:209. 长度最小的子数组-中等
题目描述:给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
方法一:滑动窗口
代码如下:
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i = 0; // 滑动窗口起始位置
int sum = 0; // 滑动窗口数值之和
int res = 1e9;
int len = 0; // 滑动窗口的长度
for(int j = 0; j < nums.size(); ++j)
{
sum += nums[j];
while(sum >= target)
{
len = j - i + 1; // 子序列的长度
res = res < len ? res : len; //更新最小的长度
sum -= nums[i];
++i;
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return res == 1e9 ? 0 : res;
}
};
方法二:前缀和+二分法
代码如下:
//时间复杂度:O(nlogn)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
vector<int> sums(nums.size() + 1, 0);
if (nums.size() == 0) {
return 0;
}
for(int i = 1; i <= nums.size(); ++i)
{
sums[i] = sums[i - 1] + nums[i - 1]; // 前缀和
}
if(sums[nums.size()] < target) // 所有值加起来小于目标值
return 0;
int ans = INT32_MAX;
for(int j = 1; j < sums.size(); ++j)
{
int temp = target + sums[j - 1]; // 前缀和加上目标序列的值
// 在剩余序列中采用二分法寻找最小的大于等于temp的前缀和
int left = j;
int right = sums.size();
while(left < right)
{
int mid = left + ((right - left) >> 1);
if(sums[mid] >= temp)
{
ans = ans < (mid - j + 1) ? ans : (mid - j + 1);
right = mid;
}
else
left = mid + 1;
}
}
return ans == INT32_MAX ? 0 : ans;
}
};
题目链接:59. 螺旋矩阵 II-中等
题目描述:
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
代码如下:
//时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
//空间复杂度 O(1)
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> mat(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int count = 1;
int edge = 1; // 边缘厚度,每循环一个圈后厚度+1
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
int i, j;
while(loop--)
{
// 下面开始的四个for就是模拟转了一圈,遵循左开右闭原则
for(j = starty; j < n - edge; ++j)
{
mat[startx][j] = count++;
}
for(i = startx; i < n - edge; ++i)
{
mat[i][j] = count++;
}
for(; j > starty; --j)
{
mat[i][j] = count++;
}
for(; i > startx; --i)
{
mat[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1
++startx;
++starty;
// 第二圈开始的时候,边缘厚度加1
++len;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if(n % 2)
{
mat[n / 2][n / 2] = n * n;
}
return mat;
}
};
标签:target,nums,int,元素,随想录,++,vector,数组
From: https://www.cnblogs.com/lurk3r/p/18028050