携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情
题目链接:1260. 二维网格迁移
题目描述
给你一个 m 行 n 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。
每次「迁移」操作将会引发下述活动:
- 位于
grid[i][j]的元素将会移动到grid[i][j + 1]。 - 位于
grid[i][n - 1]的元素将会移动到grid[i + 1][0]。 - 位于
grid[m - 1][n - 1]的元素将会移动到grid[0][0]。
请你返回 k 次迁移操作后最终得到的 二维网格。
提示:
m == grid.lengthn == grid[i].length1 <= m <= 501 <= n <= 50-1000 <= grid[i][j] <= 10000 <= k <= 100
示例 1:
输入: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出: [[9,1,2],[3,4,5],[6,7,8]]
示例 2:
输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]
示例 3:
输入: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
输出: [[1,2,3],[4,5,6],[7,8,9]]
整理题意
将二维数组进行「迁移」操作 k 次,对于每一次迁移为将二维数组中的每个整数向右整体移动一格,如果位于二维数组中最后一列的元素则移动至下一行的第一个位置,位于最后一行最后一列的元素移至第一行第一列的位置。按照上述规则移动 k 次,返回将二维数组进行「迁移」操作 k 次后的结果。
解题思路分析
由于题目数据范围较小,采用暴力模拟的方式也是可以通过的(比如队列模拟 k 次「迁移」操作)。
一维展开
根据「迁移」操作的规则我们可以发现,将二维数组每一行按照顺序进行首尾连接形成一个一维数组,那么对于「迁移」操作可以理解为将一维数组进行整体向右循环移动的操作。那么考虑在一维数组中移动前后的位置关系(假设原来的整数在二维数组中的位置为 grid[i][j]):
- 移动前在展开的一维数组中的位置为:
i * m + j(m为二维数组的列数) - 移动后在展开的一维数组中的位置为:
(i * m + j + k) % (n * m)(n为二维数组的行数,m为二维数组的列数) - 那么再将一维数组转化为
n * m的二维数组对应的位置为:grid[index / m][index % m](index的值为在一维数组中移动后的位置:index = (i * m + j + k) % (n * m))
具体实现
- 遍历二维数组中每个元素;
- 计算每个元素在一维数组中向右循环移动
k次后的位置; - 再将一维数组转换为二维数组中的位置即可。
复杂度分析
- 时间复杂度:,其中
m和n分别为网格的行列数。 - 空间复杂度:。返回值不计入空间复杂度。
代码实现
class Solution {
public:
vector<vector<int>> shiftGrid(vector<vector<int>>& grid, int k) {
int n = grid.size(), m = grid[0].size();
vector<vector<int>> res(n, vector<int>(m));
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int index = (i * m + j + k) % (m * n);
res[index / m][index % m] = grid[i][j];
}
}
return res;
}
};
总结
- 该题的核心思想为 将二维数组转化为一维数组进行循环右移操作,再将一维数组转换为二维数组 即可。
- 将二维数组转化为一维数组,再将一维数组转换为二维数组的思想不用显性转化,可以通过下标直接计算从而优化空间复杂度。
- 测试结果:
结束语
过去成就现在,当下决定未来。人生的答案不是想出来的,是一步步走出来的。我们能不能成为更好的自己,过上更好的生活,正依赖于我们现在所做的选择和脚下正在走的路。要相信,我们都有创造美好未来的力量。新的一天,加油!