# 25. 矩阵螺旋遍历

# 题目内容

给定一个 M 行 N 列的矩阵,矩阵中每个元素是一个非负整数。从左上角 (0, 0) 开始,按顺时针螺旋顺序遍历矩阵,对于遍历到的每个数字,计算其二进制表示中 1 的个数,如果 1 的个数是 3 的倍数,则记录该数字的坐标。请按照顺序输出满足条件的数字的坐标列表。

螺旋遍历按照从外到内进行,从 (0, 0) 出发先向右,遇到边界或已访问元素后,按 右 → 下 → 左 → 上 的顺序循环转向。

# 输入描述

输入共 M + 1 行:

  • 第一行:两个整数 M、N,表示矩阵的行数和列数
  • 接下来 M 行:每行 N 个非负整数,即二维数组 Array[M][N],整数范围 0 ≤ 元素值 ≤ 10^9

# 输出描述

按遍历顺序输出满足条件的坐标,单个坐标的格式为 (行索引,列索引),坐标之间以空格分隔;如果没有满足条件的数字则输出空。

注意:数字 0 的二进制表示中 1 的个数为 0,0 是 3 的倍数,因此数字 0 按满足条件统计输出。

# 样例

# 样例 1

输入

3 4
1 2 3 4
5 6 7 8
9 10 11 12
1
2
3
4

输出

(2,2) (1,2)
1

说明: 螺旋遍历顺序为:

(0,0)=1 → (0,1)=2 → (0,2)=3 → (0,3)=4 → (1,3)=8 → (2,3)=12 → (2,2)=11 → (2,1)=10 → (2,0)=9 → (1,0)=5 → (1,1)=6 → (1,2)=7

其中二进制表示中 1 的个数是 3 的倍数的数字:

  • 11 = 1011(2),有 3 个 1,坐标 (2,2)
  • 7 = 111(2),有 3 个 1,坐标 (1,2)

按遍历顺序输出 (2,2) (1,2)。

# 代码

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

let inputs = [];
rl.on('line', (input) => {
    inputs.push(input.split(' ').map(Number));
})
rl.on('close', () => {
    const [m, n] = inputs.shift();
    const list = inputs;
    const used = Array.from({ length: m }, () => Array.from({ length: n }, () => false));
    const ans = [];

    const dfs = (x, y, t) => {
        // 关键:进入时先检查,防止重复
        if (x < 0 || x >= m || y < 0 || y >= n || used[x][y]) {
            return;
        }

        used[x][y] = true;
        const val = list[x][y];

        // 统计二进制中 1 的个数
        const len = val.toString(2).split('').filter(c => c === '1').length;
        if (len % 3 === 0) {
            ans.push(`(${x},${y})`);
        }

        if (t === 'r') {
            if (y + 1 < n && !used[x][y + 1]) {
                dfs(x, y + 1, 'r');
            } else if (x + 1 < m && !used[x + 1][y]) {
                dfs(x + 1, y, 'd');
            }
        } else if (t === 'd') {
            if (x + 1 < m && !used[x + 1][y]) {
                dfs(x + 1, y, 'd');
            } else if (y - 1 >= 0 && !used[x][y - 1]) {
                dfs(x, y - 1, 'l');
            }
        } else if (t === 'l') {
            if (y - 1 >= 0 && !used[x][y - 1]) {
                dfs(x, y - 1, 'l');
            } else if (x - 1 >= 0 && !used[x - 1][y]) {
                dfs(x - 1, y, 'u');
            }
        } else if (t === 'u') {
            if (x - 1 >= 0 && !used[x - 1][y]) {
                dfs(x - 1, y, 'u');
            } else if (y + 1 < n && !used[x][y + 1]) {
                dfs(x, y + 1, 'r');
            }
        }
    }

    dfs(0, 0, 'r');
    console.log(ans.join(' '));
});
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