59.螺旋矩阵II
题目描述:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ]
思考
螺旋矩阵没有暴力破解,只能通过四个for循环重复实现对不同数字的输入。螺旋矩阵的重要点在于判断最后一个列的数字个数和奇数大小矩阵时的中间位置的数字。
整个矩阵的实现是由两组循环实现的,最外层是while循环,用来控制一周的整体循环,每一行通过一个for循环实现一行内的输入输出。
处理规则:循环不变量原则
按左闭右开的规则对各边进行遍历,都从第一个节点开始处理,到最后一个节点不处理。
定义的i对应startx,j对应starty,二维数组中i控制行的数量,j控制列的数量。
每层长度通过offset进行控制,最外层就是1,每往内一层即+1。
螺旋矩阵的数字输入通过count进行计数,在每个for循环内都要自增一次
代码如下:
class Solution {
public:
vector<vector<int>> generateMatrix(int n){
vector<vector<int>> res(n, vector<int>(n, 0));//使用vector定义二维数组
int startx = 0, starty = 0;//定义好一个起始位置
int offset = 1;//定义一个终止位置并初始值为1,
int count = 1; //定义计数的初值为1
while( n/2){//这里n/2用来判断转了几圈,若n为奇数,最中间的数直接赋值
for(j = startx; j < n - offset; j++){
/*因为一般for里面就是i=0,但是现在i必须要从起始位置出发,
而且这个位置是会变得 ,另外这里用j不用i是因为..
阵类似【i,j】的i不变 j往右边移动 */
nums[startx][j] = count++;//第一行的数遍历完成
}
for(i = starty; i < n - offset; i++){
/*因为输出的是一个正方形的螺旋矩阵,每一条边都是n-offset
*/
sums[i][j] = count++;/*第一遍便利结束,相当于第一行结束转至一列
而此时二维数组的j是不变的,所以不应该是starty*/
}
for(; j > starty; j--){/*这里就不需要对j进行初始化操作,因为这时是
第三条遍历操作,ij都是最大值,而ij要满足左闭右开的原则,j》starty
*/
nums[i][j] = count++;//继续进行赋值操作
}
for(; i > startx; i--){/*同上类似*/
nums[i][j] = count++;
}
/*外圈转完一圈,开始内圈, 第二圈开始的时候,起始位置要各自加1,
例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)*/
startx++;
starty++;
offset++;//这里的offset的含义是往里缩小的位数,看似加一,实则缩减一
}
if(n % 2 ==1){
nums[i][j] = count;//这是n为奇数时,走到中间的位置,等于count就行了
}
return nums;
}
}
数组总结篇
首先要知道数组在内存中的存储方式,这样才能真正理解数组相关的面试题,数组是存放在连续内存空间上的相同类型数据的集合。数组可以方便的通过下标索引的方式获取到下标下对应的数据。
举一个字符数组的例子,如图所示:
最值得注意的几点:
1、数组下标都是从0开始的
2、数组内存空间的地址时连续的,所以在删除或者增添元素时,难免要移动其他元素的地址。
3、使用C++的话,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
4、数组的元素是不能删的,只能覆盖。
数组的经典题目:
二分法
704、二分查找-简单
35、搜索插入位置-简单
34.在排序数组中查找元素的第一个和最后一个位置-中等
69.x 的平方根-简单
367.有效的完全平方数-简单
双指针法
27、移除元素-简单
26.删除排序数组中的重复项-简单
283.移动零-简单
844.比较含退格的字符串-简单
977.有序数组的平方-简单
滑动窗口
904.水果成篮-中等
76.最小覆盖子串-困难
209.长度最小的子数组-中等