关于螺旋矩阵||

给定一个正整数 `n`,生成一个包含 1 到 `n^2` 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

思路:

  1. > 区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。
  2. 循环矩阵就是转一个圈,遍历每个圈的上下左右四条边;
  3. 根据定义的区间如左闭右开作为每条边的循环条件进行元素赋值;
  4. n/2的值就是要转几圈,但n为奇数、偶数时不一样,  奇数时通过n%2来判断是否有剩余一个元素;
  5. 遍历内圈时,每条边:更新起始位置++;控制终止位置的变量offset++;

关于二维数组:

1. 理解二维数组的定义:`vector<vector<int>> res(n, vector<int>(n, 0))`;//n 代表外围数组的元素个数,也就是行数;`vector<int>(n, 0)`代表列数和初始值
2. 二维数组的输出,j < res[0].size()获取列数
3. **二维数组在内存的空间地址是连续的么?**

**二维数组在内存中不是 `3*4` 的连续地址空间,而是四条连续的地址空间组成**

代码:

#include<iostream>
#include<string>
#include<vector>

using namespace std;
//给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
class Solution {
public:
	vector<vector<int>> generateMatrix(int n) {
		vector<vector<int>> res(n, vector<int>(n, 0));
		int startX = 0;
		int startY = 0;
		int offset = 1;
		int count = 1; // 用来给矩阵中每一个空格赋值
		int loop = n / 2; 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
		int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
		int i , j;//矩阵的位置
		while (loop --)
		{
			i = startX;
			j = startY;
			//上
			for (j = startY; j < n - offset; j++) {
				res[i][j] = count++;
			}
			//右
			for (i = startX; i < n - offset; i++) {
				res[i][j] = count++;
			}
			//下
			for (; j > startY; j--) {
				res[i][j] = count++;
			}
			//左
			for (; i > startX; i--) {
				res[i][j] = count++;
			}
			 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
			startX++; startY++;
			// offset 控制每一圈里每一条边遍历的长度
			offset++;
		}
		// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
		if (n % 2) {
			res[mid][mid] = count++;
		}
		return res;
	}
};

int main() {

	Solution solution;
	vector<vector<int>> res = solution.generateMatrix(5);
	for (int i = 0; i < res.size(); i++) {
		for (int j = 0; j < res[0].size(); j++) {
			cout << res[i][j] << " ";
		}
		cout << endl;
	}
	system("pause");
	return 0;
}
//输出
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

关于螺旋矩阵

描述:给你一个 `m` 行 `n` 列的矩阵 `matrix` ,请按照 **顺时针螺旋顺序** ,返回矩阵中的所有元素。

思考:

对于不规则矩阵,应该如何控制遍历次数,遍历过后并对剩余元素做赋值?结合已加次数`count`与矩阵元素`nums`比较是否继续循环

难点就在于是否添加完了所有参数进`vector<int> res`?有时候添加多了。加入已加次数`count`<`nums`这个条件

不断修修改改终于提交成功.......

#include<vector>
#include<iostream>
#include<string>
using namespace std;

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int startX = 0;
        int startY = 0;
        int offset = 1;
        int count = 0;//记录遍历元素个数
        int row = matrix.size();//行数
        int columns = matrix[0].size();//列数
        int loop = max(row, columns)/2;
        int nums = row * columns;//个数
        vector<int> res;
        int i, j;
        cout << "nums: " << nums << " loop = " << loop << " row = " << row << " columns = " << columns << endl;

        while (loop-- && count < nums) {
            i = startX;
            j = startY;
            cout << " count = " << count << endl;
            if (row == 1 || columns == 1) {//针对
                if (row == 1)
                {
                    for (int j = 0; j < columns; j++) {
                        res.push_back(matrix[0][j]);
                    }
                    return res;
                }
                else {
                    for (int i = 0; i < row; i++) {
                        res.push_back(matrix[i][0]);
                    }
                    return res;
                }
                
            }
            //上
            for (j = startY; j < columns - offset; j++, count++) {
                cout << " 上:i = " << i << " j = " << j << "  ";
                res.push_back(matrix[i][j]);
            }
            cout << endl;
            //右
            for (i = startX; i < row - offset; i++, count++) {
                cout << " 右:i = " << i << " j = " << j << "  ";
                res.push_back(matrix[i][j]);
            }
            cout << endl;
            //下
            for (; j > startY && count < nums; j--, count++) {
                cout << " 下:i = " << i << " j = " << j << "  ";
                res.push_back(matrix[i][j]);
            }
            cout << endl;
            //左
            for (; i > startX && count < nums; i--, count++) {
                cout << " 左:i = " << i << " j = " << j << "  ";
                res.push_back(matrix[i][j]);
            }
            cout << endl;
            offset++;
            startX++;
            startY++;
        }
        if (row == columns && max(row, columns)%2 != 0 && count != nums) {
            cout << " 剩余元素 :" << matrix[max(row, columns) / 2][max(row, columns) / 2] << endl;
            res.push_back(matrix[max(row, columns) /2][max(row, columns) / 2]);
        }
        return res;
    }
};
int main() {
    vector<vector<int>> test1 = { {1, 2, 3},{4, 5, 6},{7, 8, 9} };
    vector<vector<int>> test2 = { {1, 2, 3, 4},{5,6,7,8},{9,10,11,12} };//,{13,14,15,16}
    vector<vector<int>> test3 = { {6,9,7}};//,{13,14,15,16}
    vector<vector<int>> test4 = { {2,3,4},{5,6,7},{8,9,10},{11,12,13},{14,15,16} };
    vector<vector<int>> test5 = { {1, 2, 3, 4,5,6,7,8,9,10},{11,12,13,14,15,16,17,18,19,20} };
    vector<vector<int>> test6 = { {1, 2, 3, 4,5},{6,7,8,9,10 }, { 11,12,13,14,15} };
    Solution solution;
    vector<int> res = solution.spiralOrder(test6);
    for (int i = 0; i < res.size(); i++) {
        cout << res[i] << " ";
    }
    system("pause");
    return 0; 
}

别人的方法:

这里的方法不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小

  • 1. 首先设定上下左右边界
  • 2. 其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
  • 3. 判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
  • 4. 若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
  • 5. 不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector <int> ans;
        if(matrix.empty()) return ans; //若数组为空,直接返回答案
        int u = 0; //赋值上下左右边界
        int d = matrix.size() - 1;
        int l = 0;
        int r = matrix[0].size() - 1;
        while(true)
        {
            for(int i = l; i <= r; ++i) ans.push_back(matrix[u][i]); //向右移动直到最右
            if(++ u > d) break; //重新设定上边界,若上边界大于下边界,则遍历遍历完成,下同
            for(int i = u; i <= d; ++i) ans.push_back(matrix[i][r]); //向下
            if(-- r < l) break; //重新设定有边界
            for(int i = r; i >= l; --i) ans.push_back(matrix[d][i]); //向左
            if(-- d < u) break; //重新设定下边界
            for(int i = d; i >= u; --i) ans.push_back(matrix[i][l]); //向上
            if(++ l > r) break; //重新设定左边界
        }
        return ans;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值