LintCode 374 螺旋矩阵的解决方法

最近在开心刷LintCode,其实我觉得刷题的目的就是锻炼你的解决问题的能力,不同的思想会带来不同的解决方案,找到最好的那个就是程序员的工作。但在找到最好的之前,你至少需要一点思想。

题目梗概

给定一个包含 m x n 个要素的矩阵,(m 行, n 列),按照螺旋顺序,返回该矩阵中的所有要素

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

应返回:

[1,2,3,6,9,8,7,4,5]

想法一

既然是这类题目肯定是不能N个for循环去做了,螺旋地把矩阵转化成链表,其步骤一共就四步:向左->向下->向右->向上,然后再进行循环。那么我们只需要定义出这四个函数,同时在每个函数内判断出啥时候该转弯(边际条件)就行了。

代码:

public class Solution {
    /**
     * @param matrix a matrix of m x n elements
     * @return an integer list
     */
    public List spiralOrder(int[][] matrix) {
        // Write your code here
        List ret = new ArrayList() ;
        if(matrix.length == 0)
        {
            return ret;
        }
        int size = (matrix.length) *(matrix[0].length);
        int n = 1;
        while(ret.size() != size)
        {
            ret.addAll(onesplit(matrix , n));
            ret.addAll(twosplit(matrix , n));
            ret.addAll(threesplit(matrix ,n));
            ret.addAll(foursplit(matrix , n));
            n++;
        }
        return ret;

    }
    public List onesplit(int [][] matrix , int n) { //(0,0) - > (0,4)
        List ret = new ArrayList() ;
        int limit = matrix[0].length -n + 1;
        for (int i = n-1 ; i < limit ; i++) {
            ret.add(matrix[n-1][i]);
        }
        return ret;
    }
        public List twosplit(int [][] matrix , int n) {//(1,4) - > (4,4)
        List ret = new ArrayList() ;
        int limit = matrix.length - n + 1 ;
        for (int i = n ; i < limit; i++) {
            ret.add(matrix[i][matrix[0].length - n]);
        }
        return ret;    
    }
        public List threesplit(int [][] matrix , int n) { //(4,3) - > (4,0)
        List ret = new ArrayList() ;
        int start = matrix[0].length - n -1 ;
        for (int i = start; i >= n-1 ; i--) {
            ret.add(matrix[matrix.length - n ][i]);
        }
        return ret;
    }
        public List foursplit(int [][] matrix , int n) {//(3,0) - > (1,0)
        List ret = new ArrayList() ;
        int start = matrix.length - n -1 ;
        for (int i = start; i >= n ; i--) {
            ret.add(matrix[i][n-1]);
        }
        return ret;
    }
}

整体思路就是依次向四个方向走,每次走到该转向的时候都把这个方向的最长路径减一,这样就能走出螺旋了。

想法很好,思考一下复杂度也应该是O(N)吧,但是Submit后给我返回了个“TLE”

既然TLE了,这个算法肯定是不行的,换个思路吧。


想法二

我们还是假装在一个矩阵上走路,不过现在我们一次只走一格,每走一格我们都去想有没有走到“头”,如果到头了就转向吧,同时每次转向将下次走这个方向的“头”的数值-1

代码实现如下:

public class Solution {
    /**
     * @param matrix a matrix of m x n elements
     * @return an integer list
     */
    public List spiralOrder(int[][] matrix) {
        // Write your code here
        List ret = new LinkedList ();
        if(matrix.length == 0)
        {
            return ret;
        }
        int m = 0;
        int n = 0;
        int flag = 0;
        int limit_1 = matrix.length -1; //竖着的
        int limit_2 = matrix[0].length -1; //横着的
        int size = matrix.length * matrix[0].length;
        int limit_3 = 1;//竖着的
        int limit_4 = 0;//横着的
        while(ret.size()!=size)
        {
            ret.add(matrix[m][n]);

            if(flag == 0){
                //横着往右走
                if( n == limit_2){
                    flag = 1;
                    limit_2--;
                    m++;
                    continue;
                }
                n++;
            }
            else if(flag == 1){
                //竖着往下走

                if( m == limit_1){
                    flag = 2;
                    limit_1--;
                    n--;
                    continue;

                }
                m++;
            }
            else if(flag == 2){
                //横着往左走

                if( n == limit_4){
                    flag = 3;
                    limit_4++;
                    m--;
                    continue;
                }
                n--;
            }
            else if(flag == 3){
                //竖着往上走

               if(m == limit_3){
                    flag = 0;
                    limit_3++;
                    n++;
                    continue;
                }
                m--;
            }

        }
        return ret;
    }
}

然后果然AC了,还是蛮开心的,通过把两个循环拆成一个成功解决了TLE的问题,不过代码中很多IF判断其实应该用switch,不够简洁。


希望能遇上更多的TLE加深我对算法思路的认识

你可能感兴趣的:(问题解析,算法学习)