最近在開心刷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<Integer> spiralOrder(int[][] matrix) {
// Write your code here
List<Integer> ret = new ArrayList<Integer>() ;
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<Integer> onesplit(int [][] matrix , int n) { //(0,0) - > (0,4)
List<Integer> ret = new ArrayList<Integer>() ;
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<Integer> twosplit(int [][] matrix , int n) {//(1,4) - > (4,4)
List<Integer> ret = new ArrayList<Integer>() ;
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<Integer> threesplit(int [][] matrix , int n) { //(4,3) - > (4,0)
List<Integer> ret = new ArrayList<Integer>() ;
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<Integer> foursplit(int [][] matrix , int n) {//(3,0) - > (1,0)
List<Integer> ret = new ArrayList<Integer>() ;
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<Integer> spiralOrder(int[][] matrix) {
// Write your code here
List<Integer> ret = new LinkedList<Integer> ();
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加深我對算法思路的認識