数组(有序数组的平方)
- 例题1(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)的算法解决。如果先平方再排序,按照快排的时间复杂度也是O(nlgn),不符合题目要求。
又因为数组是非递减顺序,因此平方后最大的数会出现在两头,而不是数组中间,开一个大小相同k的新数组,采用双指针方法。一个指向0,一个指向末尾,两数比较,将较大的数放入新数组末尾k,再将k–。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
//函数返回值是vector,在主函数调用该函数用vector来接收
int k = nums.size() - 1;
vector<int> 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;
}
};
数组(长度最小的子序列)
- 例题1(209题)给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
- 示例:
输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。要求时间复杂度O(n)
暴力法(很明显,暴力法时间复杂度为O(n*n),不满足要求)
两层嵌套循环,依次找每个元素往后相加是否大于等于目标,一旦找到就记录当前个数,并进入下一个元素的循环。
滑动窗口(时间复杂度为O(n),第一层for循环)
用两个下标表示窗口的左右边界,不断改变窗口的左右边界,得到结果。
如果窗口第一个数大于等于目标,直接退出循环返回1
如果窗口第一个数小于目标,将右边界向前,直到找到大于等于目标的地方,如果找到了,将左边界向前,找到满足要求的最短序列。如果小于目标,又将右边界向前,依次。
class Solution {//滑动窗口:左右控制窗口大小,如果不够,右边界往前;如果找到大于的位置,将左边界往前移,找到最小处。下次再从right处作为left开始找
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left=0,right=0,r=INT32_MAX,sum=0,min;
for(right=0;right<nums.size();right++)
{
sum+=nums[right];
while(sum>=target)
{
min=right-left+1;
r=r<min?r:min;//如果找到了子序列更新结果
sum-=nums[left];
left++;//滑动窗口即时调整左边界
}
}
r=(r==INT32_MAX)?0:r;//如果r改变则为最小值,没改变则为0
return r;
}
};
- 例题2(904)你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
加入哈希表,表示子序列中的数种类,当加入重复的键key时,key的value会叠加,表示该key的个数。
因此,当哈希表的桶大于2时,可以找到第一个种类通过其值找到其重复的个数。
当某个数的value–之后为零,表示该数只有一个,后面没有重复,应该在哈希表中擦除。
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map<int, int> kind;
int i = 0, j = 0,r=0;
for(j=0;j<fruits.size();j++)//当种类小于等于2时,右边界一直向前
{
kind[fruits[j]]++;//将数组存入哈希表
while (kind.size() > 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;
}
};
- 例题3(76题)最小覆盖子串(后续补充)
数组(螺旋矩阵)
- 例题1(59题)给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//用四个数来限制横纵坐标的上下左右边界,用一个变量i来表示每次变动的方向
int top=0, bottom=n-1, left=0, right=n-1;
int i;
vector<vector<int>> num(n, vector<int>(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<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size();//二维vector的行数和列数
int left = 0, right = n - 1, top = 0, bottom = m - 1;
int i;
vector<int> nums(m * n);
int k = 0;
while(k<m*n)
{
for (i = left; i <= right; i++)
{
if(k==m*n) break;
nums[k++] = matrix[top][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];
//如果if写在这里会导致下标溢出,因为加入k=m*n-1的元素后,k++为m*n超出内存
}
left++;
}
return nums;
}
};
- 例题3(29题)与54相同,顺时针打印二维数组,但多了一个判断条件(如果输入的容器xxx.empty()为真,则返回一个空容器)
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> 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<int> 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;//输入容器为空的话,返回一个空容器
}
};