是否有一个很好的算法来检查一行或一列中是否有5个相同的元素,或者对角线给出方形矩阵,比如6x6?
有一种天真算法可以迭代每个点然后对于矩阵中的每个点,遍历该行,然后是对角线。我想知道是否有更好的方法。
答案 0 :(得分:3)
您可以在字典中保留直方图(映射元素类型 - > int)。然后你迭代你的行或列或对角线,然后递增histogram[element]
,并在最后检查以查看直方图中是否有任何5,或者如果你可以允许超过5个副本,你可以只是任何元素达到5后停止。
简单,一维,例如:
m = ['A', 'A', 'A', 'A', 'B', 'A']
h = {}
for x in m:
if x in h:
h[x] += 1
else:
h[x] = 1
print "Histogram:", h
for k in h:
if h[k]>=5:
print "%s appears %d times." % (k,h[k])
输出:
Histogram: {'A': 5, 'B': 1}
A appears 5 times.
基本上,h[x]
将存储元素x
在数组中出现的次数(在您的情况下,这将是当前行,或列或对角线)。元素不必连续出现,但每次开始考虑新的行/列/对角线时,计数都会重置。
答案 1 :(得分:1)
您可以在单次传递中检查整数矩阵中是否有相同的元素。
假设n是矩阵的大小,m是最大的元素。我们有n列,n行和1对角线。 Foreach列,行或对角线我们最多有n个不同的元素。
现在我们可以创建一个包含(n + n + 1)*(2 * m + 1)元素的直方图。代表 行,列和对角线,每个都包含至多n个不同的元素。
size = (n + n + 1) * (2 * m + 1)
histogram = zeros(size, Int)
现在棘手的部分是如何更新这个直方图?
在伪代码中考虑这个函数:
updateHistogram(i, j, element)
if (element < 0)
element = m - element;
rowIndex = i * m + element
columnIndex = n * m + j * m + element
diagonalIndex = 2 * n * m + element
histogram[rowIndex] = histogram[rowIndex] + 1
histogram[columnIndex] = histogram[columnIndex] + 1
if (i = j)
histogram[diagonalIndex] = histogram[diagonalIndex] + 1
现在你所要做的就是迭代抛出直方图并检查是否有一个元素&gt; ķ
答案 2 :(得分:0)
对于行,您可以保留一个计数器,该计数器指示您当前拥有的行中有多少相同的元素。为此,请遍历行和
同样的原理也可以应用于列和对角线。您可能希望对列(每列一个元素)和对角线使用计数器数组,以便您可以迭代矩阵一次。
我为一个较小的案例做了一个小例子,但你可以很容易地改变它:
n = 3
matrix = [[1, 2, 3, 4],
[1, 2, 3, 1],
[2, 3, 1, 3],
[2, 1, 4, 2]]
col_counter = [1, 1, 1, 1]
for row in range(0, len(matrix)):
row_counter = 1
for col in range(0, len(matrix[row])):
current_element = matrix[row][col]
# check elements in a same row
if col > 0:
previous_element = matrix[row][col - 1]
if current_element == previous_element:
row_counter = row_counter + 1
if row_counter == n:
print n, 'in a row at:', row, col - n + 1
else:
row_counter = 1
# check elements in a same column
if row > 0:
previous_element = matrix[row - 1][col]
if current_element == previous_element:
col_counter[col] = col_counter[col] + 1;
if col_counter[col] == n:
print n, 'in a column at:', row - n + 1, col
else:
col_counter[col] = 1
我省略对角线以保持示例简洁明了,但对于对角线,您可以使用与在列上使用相同的原则。前一个元素将是以下之一(取决于对角线的方向):
matrix[row - 1][col - 1]
matrix[row - 1][col + 1]
请注意,在第二种情况下,您需要付出额外的努力。例如,从右到左遍历内循环中的行。
答案 3 :(得分:0)
您最好的方法可能取决于您是否控制元素的位置。
例如,如果您正在构建游戏并将最新元素放置在网格上,则可以捕获与该点相交的垂直,水平和对角线条的四个字符串,并在每个条带上使用相同的算法计算每个元素并评估总数。算法可能略有不同,具体取决于您是否计算六个中的五个连续元素,或者只要总数为五个就允许间隙。
答案 4 :(得分:0)
我认为你不能避免迭代,但你至少可以对所有元素进行异或,如果结果是0 =&gt;他们都是平等的,那么你不需要做任何比较。
答案 5 :(得分:0)
您可以尝试使用一些启发式方法来改进您的方法:使用矩阵大小的知识来排除不适合的元素序列并暂停不必要的计算。如果给定的矢量大小为6,你想要找到5个相等的元素,前3个元素是不同的,进一步的计算没有任何意义。
如果连续5个相等的元素很少发生,这种方法可以给你一个显着的优势。
答案 6 :(得分:0)
如果将行/列/对角线编码为位图,“连续五行”表示“掩码%31 == 0&amp;&amp; mask / 31 == power_of_two”
如果你想把六合一的情况视为五行,最简单的方法可能是:
for ( ; !(mask & 1) ; mask >>= 1 ) {;}
return (mask & 0x1f == 0x1f) ? 1 : 0;
也许Stanford比特调整部门有一个更好的解决方案或建议不需要循环?