我注册了一些在线代码竞赛,其中一个问题是你在一定的k转之后计算一个点在x,y范围内的一个点的位置。我能够通过一个while循环和4个条件语句进行K迭代来解决这个问题,并且它在一定程度上起作用。我总是会在他们的一个“隐藏测试”中受到时间限制。
让我谈谈这个问题,我正在查看其他人的代码并注意到这个很酷的预测算法有效,而不是O(k * n),但基本上是O(2 * n)(n =语句数量)在循环中,k =步数)。有人可以解释他正在使用的数学理论吗?
EDGAR_G6的解决方案:
int[] chessBishopDream(int[] s, int[] xy, int[] dir, int k) {
int k1;
for (int i = 0; i< 2; i++) {
if (dir[i] > 0)
k1 = k - 2*s[i] + xy[i];
else
k1 = k - (xy[i] + 1);
k1 = k1 % (2*s[i]);
xy[i] = k1 % s[i];
System.out.println(xy[i]);
System.out.println(k1);
if (k1 >= s[i])
xy[i] = k1 - 2 * xy[i] - 1;
xy[i] %= s[i];
}
return xy;
}
以下是问题:question on code fights
谢谢!
直接来自上面的链接就是问题所在:
在ChessLand中,有一位小而自豪的国际象棋主教带着一个反复出现的梦想。在梦中,主教发现自己身处一个n×m的棋盘上,每个边缘都有镜子,它不是一个主教,而是一道光线。这条光线只沿着对角线移动(主教即使在梦中也无法想象任何其他类型的移动),它永远不会停止,一旦它到达棋盘的边缘或角落,它就会从它反射并继续前进。
给定光线的初始位置和方向,在k步之后找到它的位置,其中一步意味着从一个单元移动到相邻单元或从板的一角反射。
实施例
For boardSize = [3, 7], initPosition = [1, 2],
initDirection = [-1, 1] and k = 13, the output should be
chessBishopDream(boardSize, initPosition, initDirection, k) = [0, 1].
这是主教的道路:
[1, 2] -> [0, 3] -(reflection from the top edge)-> [0, 4] ->
[1, 5] -> [2, 6] -(reflection from the bottom right corner)-> [2, 6] ->
[1, 5] -> [0, 4] -(reflection from the top edge)-> [0, 3] ->
[1, 2] -> [2, 1] -(reflection from the bottom edge)-> [2, 0] -(reflection from the left edge)->
[1, 0] -> [0, 1]
答案 0 :(得分:5)
我用JavaScript编写了一个解决方案,我将尝试描述我的方法。
首先,我“手动”沿着一个维度走过一系列位置。
例如,在宽度为3且高度为1的棋盘上,如果主教从方形0开始并向正方向移动,则其位置遵循以下模式:
0 1 2 2 1 0 0 1 2 2 1 0 0 1 ...
请注意,图案在6之后重复。另请注意(自己尝试),即使高度大于1,此图案也会保持不变。基本上,您一次只能考虑一个维度。
所以现在,对于我描述的起始条件,我可以告诉你任何k
的最终位置:
positions = [0, 1, 2, 2, 1, 0]
final = positions[k % 6]
我们是如何获得positions
的?我们通过人工观察做到了,但我们应该能够提出一个公式。因为数字上升然后再次下降,我认为计算该值的一个好方法是使用距离中心的距离(在我们的0到5的范围内为2.5)。如果我们取2.5 - n
的绝对值,我们得到这个:
2.5, 1.5, 0.5, 0.5, 1.5, 2.5
从2.5
减去我们的信息:
0, 1, 2, 2, 1, 0
这正是我们想要的。
一点点思考和试验应该表明,同样的事情在负面方向和任何起始位置都有效。对于3号,我们可以使用:
modulus = 6
middle = 2.5
newPosition = middle - abs(middle - (position + (k * direction)) % modulus)
推广到任何尺寸:
modulus = size * 2
middle = (modulus - 1) / 2
此时,我们可以在恒定时间内解决任何k
的问题:
function chessBishopDream(boardSize, initPosition, initDirection, k) {
// this array will hold the two coordinates of the final position
var finalPosition = [];
// first coordinate, second coordinate
for (var i = 0; i < 2; i++) {
var position = initPosition[i];
var direction = initDirection[i];
// simple addition, ignoring the edges
var newPosition = position + direction * k;
// period of the repeating pattern (e.g. 0 1 2 2 1 0 0 1 ...)
var modulus = boardSize[i] * 2;
// this is our "index" into the pattern
newPosition %= modulus;
// ensure a positive result of the modulo
if (newPosition < 0) {
newPosition += modulus;
}
var middle = (modulus - 1) / 2;
finalPosition[i] = middle - Math.abs(middle - newPosition);
}
return finalPosition;
}
答案 1 :(得分:1)
看起来这个解决方案使用观察结果x和y部分的位置独立地以相同的速度变化。
相同的速度意味着在k移动后每个坐标将改变k次。独立地表示可以在不知道y坐标的情况下计算x坐标的变化。
很难遵循实际计算,但它有这些步骤
2*s[i]
k1 % (2*s[i])
计算所有反射后的坐标