代码随想录算法训练营Day2 | 977 有序数组的平方 、23 长度最小的子数组、59 螺旋矩阵II

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]
  • 暴力法

    • 先平方,对新的数组进行排序;
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
		//对原数组全部平方
		for (int i = 0; i < nums.size(); i++) {
			nums[i] = pow(nums[i], 2);
		}
		//对平方后的数组进行排序
		for (int i = 0; i < nums.size(); i++) {
			for (int j = i + 1; j < nums.size(); j++) {
				if (nums[j] < nums[i]) {
					int temp = nums[i];
					nums[i] = nums[j];
					nums[j] = temp;
				}
			}
		}
		return nums;
	}
};	
  • 双指针思路

    • 平方之后大元素在两边,小元素在中间
    • 一个指针(j)指向数组尾,一个指针(i)指向数组首,对比平方大小,将对应位置的元素平方放到新的Results数组中
      • for( int i = 0; j = numsize-1; i<=j ): j往前走,i往后走,直至相遇遍历完整个数组,且条件为 i <= j;相遇的时候也要将相遇的元素放到Results数组中,防止漏元素;
      • j往前走,即j对应的平方值比较大,所以去j对应的位置j--;
      • i往后走,即i对应的平方值比较大,所以去i对应的位置i++;
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
	    int k = nums.size() - 1;
	    vector<int> results(nums.size(), 0);
	    for (int i = 0, j = nums.size()-1; i <= j ;) {
		    if (pow(nums[i], 2) <= pow(nums[j], 2)) {
			    results[k--] = pow(nums[j], 2);
			    j--;
		    }
		    else{
			    results[k--] = pow(nums[i], 2);
			    i++;
		    }
	    }
	    return results;
    }
}:

23 长度最小的子数组

  • 题目描述

    •  给定一个含有 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
  • 暴力解法

    • 两次for循环,第一个for循环遍历数组的各个元素,第二个for循环从当前元素开始累加直至数组总和达到目标值,进行统计。
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
	    int result = INT32_MAX;//result 为结果长度,先置为最大数
	    int numslength = 0;//当前统计的长度
	    int sum;
	    for (int i = 0; i < nums.size(); i++) {
	    	sum = 0;//每次循环开始sum重置为零
	    	for (int j = i; j < nums.size(); j++) {
		    	sum += nums[j];
		    	//判断,得到由i对应数字开始的总和能过大于s的最短数组
		    	if (sum >= s) {
			    	numslength = j - i + 1;//取满足条件的序列的长度
			    	if (numslength < result) result = numslength;
			    	break;//找到满足的数组即可停止循环
			    }
		    }
    	}//result是否更新了,更新了则说明找到了最短序列,没更新则说明没有找到,则输出结果为零;
	    return result == INT32_MAX ? 0 : result;
    }
};
  • 双指针法

    • 一个for循环实现两个for循环的工作,滑动窗口;
    • 关键在于滑动窗口的动态移动,首先明确j对应的是滑动窗口的尾部,通过for循环遍历数组,使其每一个数字都成为过滑动窗口的尾部。
    • sum -= nums[i++];//关键之处,即在满足sum已经足够的情况下,从首部i往后移动进行缩减,使得滑动窗口尽可能的小;
    • 在不满足循环条件即sum >= s 时,窗口的尾部即 j 开始往右边滑动,满足条件窗口首部即i再开始往右边滑动,对滑动窗口进行缩减;
    • 如此反复便可以得到数组的每个尾部j所对应最小的子数组,进行比较得到对于整个数组来说长度最小的子数组;
class Solution {
public:
	//最好结合动画理解滑动过程
	int minSubArrayLen(int s, vector<int>& nums) {
		int result = INT32_MAX;
		int sum = 0;
		int numslength = 0;
		int i = 0;//i 是滑动窗口的首位置
		for (int j = 0; j < nums.size(); j++) {// j是滑动窗口的尾部
			sum += nums[j];
			while (sum >= s) {
				numslength = j - i + 1;
				if (numslength < result) result = numslength;//更新result
				sum -= nums[i++];//关键之处,即在满足sum已经足够的情况下,从首部i往后移动进行缩减,使得滑动窗口尽可能的小
			}
			//在不满足循环条件即sum >= s 时,窗口的尾部即 j 开始往右边滑动,满足条件窗口首部即i再开始往右边滑动
			//如此反复便可以得到数组的每个尾部j所对应最小的子数组;进行比较得到对于整个数组来说长度最小的子数组
		}
		return result == INT32_MAX ? 0 : result;
	}
};

59 螺旋矩阵II

  • 题目描述

    • 给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
    • 示例:
      • 输入: 3
      • 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
  • 重点

    • 本题涉及到与二维数组相关的循环,相较于一维数组,虽然复杂度提高了,但依然存在着明显的规律:正方形每层外壳都是按照1,2,3,4四个方向进行旋转的,而每次的旋转也都是按照一定的节点来推进的。

    • 循环的次数:loop = 矩阵半径/2;即转多少次圈圈;偶数自然是除以二(每一圈占两个格子)奇数最中间的那个是数字n,剩下的自然就是偶数辣,同理;
    • 左闭右开:int offset = 1;offset为当前循环离边界的距离,初始为1;例如4*4,第一行只能到0,1,2;3就已经算竖向的;因此第一次是3格*4,第二次是1格*4;每次转圈左边一格,右边一格,上边一格,下边一格,转完一圈之后offset+1;通过n-offset找到每次循环最终格子值:第一圈是4-1=3,临界格子序号是3;第二圈offset+1之后,n-offset是2即临界格子序号是2;以此类推循环;
    • startx,starty:为横纵坐标的起点,每次转圈完+1;
    • 每一圈是四个方向即四个循环:第一次循环for (j = starty; j < n - offset; j++) {nums[startx][j] = count++;}//也可以是nums[i][j] = count++;每次循环完之后i,j回到的点为新的startx,starty是一样的;每次循环的关键点在于左边界,右边界;即startx/y和offset-n;
class Solution {
public:
	vector<vector<int>> generateMatrix(int n) {
		vector<vector<int>>nums(n, vector<int>(n, 0));//定义一个n*n二维空数组
		int startx = 0;
		int starty = 0;
		int loop = n / 2;//偶数自然是除以二(每一圈占两个格子)奇数最中间的那个是数字n,剩下的自然就是偶数辣,同理;
		int offset = 1;//左闭右开,例如4*4,第一行只能到0,1,2;3就已经算竖向的循环了
		int count = 1;
		int i;
		int j;
		while (loop--) {
			i = startx;//每次循环开始的横行,循环完一次后++
			j = starty;//每次循环开始的纵行,循环完一次后++
			//满足每一个遍历都是左闭右开
			//第一次从左上到右上,横坐标i不变,纵坐标j++;
			for (j = starty; j < n - offset; j++) {
				nums[i][j] = count++;//先计数,再递增
			}
			//从右上到右下,纵坐标为刚才的j不变,横坐标i++;
			for (i = startx; i < n - offset; i++) {
				nums[i][j] = count++;
			}
			//从右下到左下,横坐标不变为刚才的i;纵坐标j--;
			for (; j > starty; j--) {
				nums[i][j] = count++;
			}
			//从左下到左上,纵坐标不变为刚才的j;横坐标i--;
			for (; i > startx; i--) {
				nums[i][j] = count++;
			}
			offset++;
			startx++;
			starty++;
		}
		//如果是奇数,勿忘中心
		if (n % 2) {
			nums[n / 2][n / 2] = count;
		}
		return nums;
	}
};

总结&&碎碎念

题做了,笔记也写了,就是没有腾到博客上,拖延症啊拖延症……上周周四周五不少课,周六周日一边忙一边玩,刷题耽搁了两天,得速速补上。至于博客,一开始比较习惯用幕布来记录要点,比较清晰,但是转到CSDN的博客上面还是有点小麻烦,不过做过一两次还是清晰了不少流程(还是得吐槽CSDN这个编辑撤回Crtl+Z,Tab键,分级标题和正文之间的切换,是我不习惯还是说本身就很难用呢~)

任务还是很重的,为了理想的目标和自己,得加把劲了(记得要补一下数组的总结~)

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
代码随想录算法训练是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值