示例 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)的算法解决。如果先平方再排序,按照快排的时间复杂度也是O(nlgn),不符合题目要求。
又因为数组是非递减顺序,因此平方后最大的数会出现在两头,而不是数组中间,开一个大小相同k的新数组,采用双指针方法。一个指向0,一个指向末尾,两数比较,将较大的数放入新数组末尾k,再将k–。
class Solution {
public:
vector sortedSquares(vector& nums) {
//函数返回值是vector,在主函数调用该函数用vector来接收
int k = nums.size() - 1;
vector num(nums.size());
int i = 0, j = k;
while (k>=0)
{
if (nums[i] * nums[i] >= nums[j] * nums[j])
{
num[k] = nums[i]*nums[i];
k--;
i++;
}
else if (nums[i] * nums[i] < nums[j] * nums[j])
{
num[k] = nums[j]*nums[j];
k--;
j--;
}
}
return num;
}
};
暴力法(很明显,暴力法时间复杂度为O(n*n),不满足要求)
两层嵌套循环,依次找每个元素往后相加是否大于等于目标,一旦找到就记录当前个数,并进入下一个元素的循环。
滑动窗口(时间复杂度为O(n),第一层for循环)
用两个下标表示窗口的左右边界,不断改变窗口的左右边界,得到结果。
如果窗口第一个数大于等于目标,直接退出循环返回1
如果窗口第一个数小于目标,将右边界向前,直到找到大于等于目标的地方,如果找到了,将左边界向前,找到满足要求的最短序列。如果小于目标,又将右边界向前,依次。
class Solution {//滑动窗口:左右控制窗口大小,如果不够,右边界往前;如果找到大于的位置,将左边界往前移,找到最小处。下次再从right处作为left开始找
public:
int minSubArrayLen(int target, vector& nums) {
int left=0,right=0,r=INT32_MAX,sum=0,min;
for(right=0;right=target)
{
min=right-left+1;
r=r
加入哈希表,表示子序列中的数种类,当加入重复的键key时,key的value会叠加,表示该key的个数。
因此,当哈希表的桶大于2时,可以找到第一个种类通过其值找到其重复的个数。
当某个数的value–之后为零,表示该数只有一个,后面没有重复,应该在哈希表中擦除。
class Solution {
public:
int totalFruit(vector& fruits) {
unordered_map kind;
int i = 0, j = 0,r=0;
for(j=0;j 2)
{
auto it = kind.find(fruits[i]);//哈希表里种类大于2,找到第一个数赋给it
it->second--;//表示it的value值(如果加入重复的key,key的value会叠加表示重复的个数)
if (it->second == 0)//如果it只有一个,则从哈希表里擦去
{
kind.erase(fruits[i]);
}
i++;
}
r = r > (j - i + 1) ? r : (j-i+1);
}
return r;
}
};
class Solution {
public:
vector> generateMatrix(int n) {
//用四个数来限制横纵坐标的上下左右边界,用一个变量i来表示每次变动的方向
int top=0, bottom=n-1, left=0, right=n-1;
int i;
vector> num(n, vector(n));//定义一个空的n行n列的二维数组
int k = 1;//数组里的元素
while (k <= n * n)
{
for (i = left; i <= right; i++)
{
num[top][i] = k++;
}
top++;
for (i = top; i <= bottom; i++)
{
num[i][right] = k++;
}
right--;
for (i = right; i >= left; i--)
{
num[bottom][i] = k++;
}
bottom--;
for (i = bottom; i >= top; i--)
{
num[i][left] = k++;
}
left++;
}
return num;
}
};
例题2(54题)给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
class Solution {
public:
vector spiralOrder(vector>& matrix) {
int m = matrix.size(), n = matrix[0].size();//二维vector的行数和列数
int left = 0, right = n - 1, top = 0, bottom = m - 1;
int i;
vector nums(m * n);
int k = 0;
while(k= left; i--)
{
if(k==m*n) break;
nums[k++] = matrix[bottom][i];
}
bottom--;
for (i = bottom; i >= top; i--)
{
if(k==m*n) break;
nums[k++] = matrix[i][left];
//如果if写在这里会导致下标溢出,因为加入k=m*n-1的元素后,k++为m*n超出内存
}
left++;
}
return nums;
}
};
class Solution {
public:
vector spiralOrder(vector>& matrix) {
vector num;
if(!matrix.empty())//输入的容器不为空
{
int m = matrix.size(), n = matrix[0].size();
int left = 0, right = n - 1, top = 0, bottom = m - 1;
int k = 0, i;
vector nums(m * n);
while (k < m * n)
{
for (i = left; i <= right; i++)
{
if (k == m * n) break;
nums[k++] = matrix[left][i];
}
top++;
for (i = top; i <= bottom; i++)
{
if (k == m * n) break;
nums[k++] = matrix[i][right];
}
right--;
for (i = right; i >= left; i--)
{
if (k == m * n) break;
nums[k++] = matrix[bottom][i];
}
bottom--;
for (i = bottom; i >= top; i--)
{
if (k == m * n) break;
nums[k++] = matrix[i][left];
}
left++;
}
return nums;
}
else
return num;//输入容器为空的话,返回一个空容器
}
};