代码随想录-数组(有序数组的平方,最小长度子序列、螺旋矩阵)

数组(有序数组的平方)

  • 例题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;//输入容器为空的话,返回一个空容器
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值