算法-螺旋矩阵

2022/1/8 算法

螺旋矩阵实现探讨

# 题目描述

给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。

数据范围:0 ≤ (m, n) ≤ 100,矩阵中任意元素都满足 |val| ≤ 100

要求:空间复杂度 O(nm),时间复杂度 O(nm)

# 解法1

# 思路

数据按照蛇形前进,前进的任意方向时的下一步都有且只有两种情况,例如:

前进方向 == 右,下一步 只可能是 右 || 下,即x++ || y++ 前进方向 == 下,下一步 只可能是 下 || 左,即x-- || x++ 前进方向 == 左,下一步 只可能是 下 || 上,即x-- || y-- 前进方向 == 上,下一步 只可能是 上 || 右,即x++ || y--

由此蛇形前进就实现了,另外需要增加碰撞转向(下一步的值重复使用,改遍方向)

需要保存x,y的位置数组,然后与下一步的x,y进行重复检测。

# 代码

性能:运行时间:90ms 占用内存:8368KB

/**
 * 
 * @param matrix int整型二维数组 
 * @return int整型一维数组
 */
function spiralOrder( matrix ) {
    // write code here
    if(!matrix || matrix.length == 0) return []
    let data = [];
    const m = matrix.length, n = matrix[0].length;
    let x = 0, y = 0; // 当前头部数据位置
    let position = 0 // 0 右 1 下 2 左 3 上
    let indexData = [[0,0]]
    for(let i = 0; i < m*n; i++){
        let checkIndexData = indexData.map(e=>e.join()) // 历史位置数据
        if(position == 0){
            if(matrix[x][y+1] != undefined && checkIndexData.indexOf([x, y+1].join()) == -1){ // 校验
                indexData.push([x, y+1])
                position = 0
                y++
            }else if(matrix[x+1] != undefined){
                indexData.push([x+1, y])
                position = 1
                x++
            }
        }else if(position == 1){
            if(matrix[x+1] != undefined && checkIndexData.indexOf([x+1, y].join()) == -1){
                indexData.push([x+1, y])
                position = 1
                x++
            }else if(matrix[x][y-1] != undefined){
                indexData.push([x, y-1])
                position = 2
                y--
            }
        }else if(position == 2){
            if(matrix[x][y-1] != undefined && checkIndexData.indexOf([x, y-1].join()) == -1){
                indexData.push([x,y-1])
                position = 2
                y--
            }else if(matrix[x-1] != undefined){
                indexData.push([x-1,y])
                position = 3
                x--
            }
        }else if(position == 3){
            if(matrix[x-1] != undefined && checkIndexData.indexOf([x-1, y].join()) == -1){
                indexData.push([x-1,y])
                position = 3
                x--
            }else if(matrix[x][y+1] != undefined){
                indexData.push([x,y+1])
                position = 0
                y++
            }
        }
        data.push(matrix[indexData[i][0]][indexData[i][1]])
    }
    return data
}
module.exports = {
    spiralOrder : spiralOrder
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 优化

性能:运行时间:87ms 占用内存:8292KB

/**
 * 
 * @param matrix int整型二维数组 
 * @return int整型一维数组
 */
function spiralOrder( matrix ) {
    // write code here
    if(!matrix || matrix.length == 0) return []
    let data = [], 
        indexData = [[0,0]], // 历史位置数据
        x = 0, y = 0, // 当前头部数据位置
        position = 0; // 0 右 1 下 2 左 3 上
    for(let i = 0; i < matrix.length * matrix[0].length; i++){
        data.push(matrix[x][y])
        let checkIndexData = indexData.map(e=>e.join()) // 历史位置数据
        if(position == 0){
            if(matrix[x][y+1] != undefined && checkIndexData.indexOf([x, y+1].join()) == -1){ // 校验
                y++
                position = 0
            }else{
                x++
                position = 1
            }
        }else if(position == 1){
            if(matrix[x+1] != undefined && checkIndexData.indexOf([x+1, y].join()) == -1){
                x++
                position = 1
            }else{
                y--
                position = 2
            }
        }else if(position == 2){
            if(matrix[x][y-1] != undefined && checkIndexData.indexOf([x, y-1].join()) == -1){
                y--
                position = 2
            }else{
                x--
                position = 3
            }
        }else if(position == 3){
            if(matrix[x-1] != undefined && checkIndexData.indexOf([x-1, y].join()) == -1){
                x--
                position = 3
            }else{
                y++
                position = 0
            }
        }
        indexData.push([x,y])
    }
    return data
}
module.exports = {
    spiralOrder : spiralOrder
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 解法2

# 思路2

按照边框的画法,顺时针取值,外圈完了找内圈,例如:

3*4的矩阵,外圈四个方向长度分别是 [0, 0]-[x, 0] [x, 1]-[x, y] [x, y-1]-[0, x] [x-1, 0]-[1, 0]

然后 四个方向的变量向内部缩紧1top++ right-- bottom-- left++

增加圈限制,防止数据重复,当top < x_length/2 && left < y_length/2

# 代码2

性能:运行时间:87ms 占用内存:8144KB

/**
 * 
 * @param matrix int整型二维数组 
 * @return int整型一维数组
 */
function spiralOrder( matrix ) {
    // write code here
    if(!matrix || matrix.length == 0) return []
    let data = [], 
        top = 0, bottom = matrix.length - 1, // 上下边距
        left = 0, right = matrix[0].length - 1; // 左右边距
    while(top<matrix.length/2 && left<matrix[0].length/2){
        // 上左-上右
        for(let i = left; i <= right; i++){
            data.push(matrix[top][i])
        }
        // 上右-下右
        for(let i = top+1; i <= bottom; i++){
            data.push(matrix[i][right])
        }
        // 下右-下左
        if(top != bottom){
            for(let i = right-1; i >= left; i--){
                data.push(matrix[bottom][i])
            }    
        }
        // 下左-上左
        if(left != right){
            for(let i = bottom-1; i >= top + 1; i--){
                data.push(matrix[i][left])
            }
        }
        top++
        bottom--
        left++
        right--
    }
    
    return data
}
module.exports = {
    spiralOrder : spiralOrder
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 总结

两种思路性能差距不大。

第一种更贴近我的思路。