逻辑之旅

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

题意

原地顺时针翻转一个 n*n 的矩阵

 

图解

下面例子中用 5*5 矩阵做示例,如下图,我们要把该矩阵顺时针翻转90度,并且不能使用另外的矩阵空间来暂存数据,而是原地改变矩阵中数值。

我的想法是这样的:找出翻转的下标变换规律,找出需要变换的位置,将与该位置有关的四个方法(left, top, right, bottom)一次性交换值。

如下图:

首先我从最外围入手,其实整个外围的变化,可以以第一行的 (0, n-2)坐标的元素为基础开始变化,其他三个方向是跟它有关的需要同时变换的元素;

同理,第二行也找到了需要变换的坐标位置;

至于第三行,由于只有一个元素,不需要变换,当然如果你太闲或者觉得代码要统一,变换也不影响什么。(当 n 为偶数的时候,不存在单个元素)

由于上面的例子具有代表性,我们可以从中提取一些规律:

1. 变换的行坐标,从 0 到 Math.floor(n/2)(如下图 i 所示);

2. 变化的列坐标,从 i 到 n-1-i (如下图 j 所示);

3. 变换的坐标公式为:原本位于 (i, j) 的 元素,会变换到 (j, n-1-i) 位置上去。

这个在坐标变换时需要特别注意,因为我们的出发位置不一定是 (i, j),自己做数学公式代入变换的时候,要区分好不同变量,避免逻辑混乱 -- 我自己就比较容易混淆。此外,变换公式如何得到呢?写个例子,列出一些坐标的变动,再根据数据推测一下,最后把其他位置的坐标变动代入验证一下,就能得到。

 

JavaScript 代码

 主要坐标变换如下:

1 let tmp = matrix[i][j];
2 matrix[i][j] = matrix[n-1-j][i];
3 matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
4 matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
5 matrix[j][n-1-i] = tmp;

完整代码:

var rotate = function(matrix) {
    let n = matrix.length;
    let m = Math.floor(n/2);
    for(let i=0; i<m; i++){
        for(let j=i; j<n-1-i; j++){
            [matrix[i][j], matrix[n-1-j][i], matrix[n-1-i][n-1-j], matrix[j][n-1-i]]
             = [matrix[n-1-j][i], matrix[n-1-i][n-1-j], matrix[j][n-1-i], matrix[i][j]];
        }
    }
};

 

结论

做这类坐标变换的题目,主要是寻找坐标变换规律,搞清每次需要动的是哪些元素,目标明确,变换公式明确,其实就没什么大问题。

以前我做这种题目容易出错,主要是因为我心急,不想画例子来分析来看,坐标变换规律也是半懂不懂就开始写代码,偶尔写出来,都是靠运气~

由此可见,保持平稳心态,找准目标,才是真理。

posted on 2019-07-10 16:31  LinMiaoj  阅读(147)  评论(0编辑  收藏  举报