持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
面试题 16.22. 兰顿蚂蚁
一只蚂蚁坐在由白色和黑色方格构成的无限网格上。开始时,网格全白,蚂蚁面向右侧。每行走一步,蚂蚁执行以下操作。
(1) 如果在白色方格上,则翻转方格的颜色,向右(顺时针)转 90 度,并向前移动一个单位。 (2) 如果在黑色方格上,则翻转方格的颜色,向左(逆时针方向)转 90 度,并向前移动一个单位。
编写程序来模拟蚂蚁执行的前 K 个动作,并返回最终的网格。
网格由数组表示,每个元素是一个字符串,代表网格中的一行,黑色方格由 'X' 表示,白色方格由 '_' 表示,蚂蚁所在的位置由 'L', 'U', 'R', 'D' 表示,分别表示蚂蚁 左、上、右、下 的朝向。只需要返回能够包含蚂蚁走过的所有方格的最小矩形。
「示例1:」
输入: 0
输出: ["R"]
「示例2:」
输入: 2
输出:
[
"_X",
"LX"
]
「示例3:」
输入: 5
输出:
[
"_U",
"X_",
"XX"
]
「提示:」
K <= 100000
解题思路
用minX, maxX, minY, maxY保存蚂蚁走过的边界
用dp保存蚂蚁走过的位置的砖块
用blackSet保存黑色方块的位置
蚂蚁走的话只有以下几种情况
当前位置 x, y
当前位置是白色砖块,当前方向是右 -> 砖块变黑,方向变成下,走一步变成 x + 1, y
当前位置是白色砖块,当前方向是左 -> 砖块变黑,方向变成上,走一步变成 x - 1, y
当前位置是白色砖块,当前方向是上 -> 砖块变黑,方向变成右,走一步变成 x, y + 1
当前位置是白色砖块,当前方向是下 -> 砖块变黑,方向变成左,走一步变成 x, y - 1
当前位置是黑色砖块,当前方向是右 -> 砖块变白,方向变成上,走一步变成 x - 1, y
当前位置是黑色砖块,当前方向是左 -> 砖块变白,方向变成下,走一步变成 x + 1, y
当前位置是黑色砖块,当前方向是上 -> 砖块变白,方向变成左,走一步变成 x, y - 1
当前位置是黑色砖块,当前方向是下 -> 砖块变白,方向变成右,走一步变成 x, y + 1
更新边界
更新蚂蚁当前位置的砖块
最后将边界内的内容拼凑成结果
代码实现
/**
* @param {number} K
* @return {string[]}
*/
var printKMoves = function(K) {
const dp = {}, position = [0, 0],
// 蚂蚁行进的位置
positions = {
'R': [0, 1],
'L': [0, -1],
'U': [-1, 0],
'D': [1, 0],
},
// 蚂蚁在当前位置砖块颜色和方向的转换
transform = {
'R': {
'_': ['D', 'X'],
'X': ['U', '_']
},
'L': {
'_': ['U', 'X'],
'X': ['D', '_']
},
'U': {
'_': ['R', 'X'],
'X': ['L', '_']
},
'D': {
'_': ['L', 'X'],
'X': ['R', '_']
},
},
blackSet = new Set
let minX = 0, maxX = 0, minY = 0, maxY = 0, direction = 'R'
// 获取蚂蚁走过的边界
function getLimit(x, y) {
minX = Math.min(x, minX)
maxX = Math.max(x, maxX)
minY = Math.min(y, minY)
maxY = Math.max(y, maxY)
}
dp[position[0]] = []
dp[position[0]][position[1]] = '_'
let l = 0
while(l < K) {
// 现根据当前位置,取得当前位置的砖块颜色和方向,根据当前位置的砖块颜色和方向转换颜色和方向
const [x, y] = position, d = direction, p = dp[x][y], cache = transform[d][p]
direction = cache[0]
dp[x][y] = cache[1]
if (dp[x][y] === '_') {
blackSet.delete(`${x}&${y}`)
} else {
blackSet.add(`${x}&${y}`)
}
// 根据转换的颜色和方向取得下一个位置的左边,和下一个位置的砖块颜色,以及蚂蚁行进的边界
position[0] += positions[direction][0]
position[1] += positions[direction][1]
const [newx, newy] = position
if (!dp[newx] || !dp[newx][newy]) {
dp[newx] = dp[newx] || []
dp[newx][newy] = '_'
}
getLimit(newx, newy)
l++
}
// 根据蚂蚁的边界取得结果
const res = Array(maxX - minX + 1)
.fill(0)
.map(() => Array(maxY - minY + 1).fill('_'))
for (const pos of blackSet) {
const [x, y] = pos.split('&')
res[x - minX][y - minY] = 'X'
}
res[position[0] - minX][position[1] - minY] = direction
return res.map((row) => row.join(''))
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;