48. Rotate Image

题目:

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Follow up:
Could you do this in-place?

链接:  http://leetcode.com/problems/rotate-image/

题解:

in-place,按照顺时针移动整个矩阵的1/4,注意边长为奇数时的corner case。 还有方法是对折再变换的。

Time complexity - O(n2), Space Complexity - O(1)

public class Solution {
    public void rotate(int[][] matrix) {
        if(matrix == null || matrix.length == 0)
            return;
        int n = matrix.length - 1;
        
        for(int i = 0; i <= n / 2; i++) {
            for(int j = 0; j < (n + 1) / 2; j++) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[n - j][i];
                matrix[n - j][i] = matrix[n - i][n - j];
                matrix[n - i][n - j] = matrix[j][n - i];
                matrix[j][n - i] = tmp;
            }
        }
    }
}

 

Follow up是对矩阵最外部的元素,每个元素向右移动一个位置。可能药用spiral matrix一类的方法。

再Follow up可以 design一个三消游戏,类似 Candy Crush saga。

 

二刷:

这里看漏了n x n matrix,其实m = n就可以了。注意遍历的边界条件, i 可以 < n /2, 这样j就必须要 j < (n + 1) / 2来cover中间的奇数元素。还可以想得再透彻一些。还有不少大神有很好的翻转方法,先记录在reference里,留给三刷了。

Java:

Time complexity - O(n2), Space Complexity - O(1)

public class Solution {
    public void rotate(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return;
        }
        int m = matrix.length, n = matrix[0].length;
        for (int i = 0; i < m / 2; i++) {
            for (int j = 0; j < (n + 1) / 2; j++) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[m - 1 - j][i];
                matrix[m - 1 - j][i] = matrix[m - 1 - i][n - 1 - j];
                matrix[m - 1 - i][n - 1 - j] = matrix[j][n - 1 - i];
                matrix[j][n - 1 - i] = tmp;
            }
        }
    }
}

同时也做了一下 Rotate Matrix by 1, 发了一篇新文

Rotate Matrix by One 

题外话:

1/27/2016

今天群里讨论interval search tree,很精彩。我打算好好复习一下相关的知识。昨天讨论Google面试题密码箱问题,de brujin, hamiton path和 euler path,还是要好好向dietpepsi大神学习。 要扎实,反应敏捷并且准确,还要能迅速写出代码才能。现在差得还很远。

 

三刷:

这里的边界条件要注意一下。因为题目给出m = n,所以input是边长都是n的方阵。 我们旋转的方阵分为两种,一种是边长为奇数的,一种是边长为偶数的。

旋转边长为偶数的矩阵时,我们要根据  len / 2 把矩阵分为四个部分,只需要旋转左上部分就行了,比如n = 4,那么我们的条件就是 i < 2和 j < 2。  

[1, 2, 3, 4]

[5, 6, 7, 8]

[1, 2, 3, 4]

[5, 6, 7, 8]

 

另外一种是奇数边长的矩阵,这时候我们旋转的也是左上部分,不过左上部分这时候不是一个方阵,而是一个类似于三角形,或者梯形的区域。比如下图,这里其实我们要旋转的是1和2,或者1和4。假如我们同时旋转1, 2和4, 那么就会出现重复步骤造成结果不正确。

所以这时候我们对边长的界定应该是,  i < (len + 1) / 2, 即对row 添加1然后除以2,转换成偶数边长时遍历的情况, 而 j < len / 2, 对j来说不变,还是维持奇数边长时遍历的情况。当然这里我们也可以互换i 和 j。 这样处理就保证了我们在操作的时候没有多余步骤。

 

[1, 2, 3]

[4, 5, 6]

[7, 8, 9]

 

 

Java:

public class Solution {
    public void rotate(int[][] matrix) {
        if (matrix == null) return;
        int len = matrix.length;
        for (int i = 0; i < (len + 1) / 2; i++) {
            for (int j = 0; j < len / 2; j++) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[len - 1 - j][i];
                matrix[len - 1 - j][i] = matrix[len - 1 - i][len - 1 - j];
                matrix[len - 1 - i][len - 1 - j] = matrix[j][len - 1 - i];
                matrix[j][len - 1 - i] = tmp;
            }
        }
    }
}

 

 

Reference:

https://leetcode.com/discuss/20589/a-common-method-to-rotate-the-image

https://leetcode.com/discuss/38426/seven-short-solutions-1-to-7-lines

https://leetcode.com/discuss/27262/java-in-place-solution-with-explanation-easy-to-understand

 

posted @ 2015-04-17 23:31  YRB  阅读(485)  评论(0编辑  收藏  举报