【问题标题】:How to find largest square of palindrome in a matrix如何在矩阵中找到最大的回文平方
【发布时间】:2015-05-17 23:20:58
【问题描述】:

我正在尝试解决一个问题,即给定一个 nXn 方阵字符,我想从中找出最大回文方阵的大小?最大的回文方格是所有行和所有列的回文方格。

例如。 输入

a g h j k
s d g d j
s e f e n
a d g d h 
r y d g s

输出将是:

3

对应中间的正方形。我正在考虑动态编程解决方案,但无法制定递归关系。我认为尺寸应该是 a(i,j,k) 其中 i,j 是矩形的右下角,k 是回文正方形的大小。 有人可以帮我解决这个问题的递归关系吗?

编辑:

n

【问题讨论】:

  • 您可能还需要几个变量来记录您正在测试的列或行是否为有效回文
  • 没错,这就是我所坚持的,我想以 O(n^3) 的时间复杂度来做。我仍然无法得到递归关系。

标签: algorithm language-agnostic dynamic-programming


【解决方案1】:

假设你可以解决以下问题:

  • 在单元格(i, j) 结尾处是否存在横向和纵向长度不同的回文。

以上问题提示:

   boolean[][][]palindrome;//Is there any palindrome ending at (i , j) has length k
   for(int i = 0; i < n; i++){
       for(int j = 0; j < n; j++){
           palindrome[i][j][0] = true;
           palindrome[i][j][1] = true;
           for(int k = 2; k <= n; k++)
               if(data[i][j - k + 1] == data[i][j] && palindrome[i][j - 1][k - 2])
                  palindrome[i][j][k] = true; 
       } 
  }         

所以,我们可以创建两个三维数组int[n][n][n]colint[n][n][n]row

对于每个单元格(i, j),我们将计算长度为 k 的回文总数,结束于单元格 (0, j), (1, j) , ... (i, j) 和总数长度为 k 的回文数,结束于单元格 (i,0), (i, 1), ... (i, j)

for(int k = 1; k <= n; k++)
    if(there is palindrome length k horizontally, end at cell (i, j)) 
       row[i][j][k] = 1 + row[i - 1][j][k];
    if(there is palindrome length k vertically, end at cell (i, j)) 
       col[i][j][k] = 1 + col[i][j - 1][k]; 

最后,if row[i][j][k] &gt;= k &amp;&amp; col[i][j][k] &gt;= k -> 有一个平方回文长度 k 以 (i,j) 结尾。

总的来说,时间复杂度将是 O(n^3)

【讨论】:

  • 非常好的解决方案。有效。我每次都诅咒自己,我解决不了DP问题。
  • @Naman 很高兴它有帮助,你可能只需要一些练习,别担心 :)
  • 再次感谢。如果你不介意,你也可以看看这个问题吗? stackoverflow.com/questions/24863373/… 我可以找到解决方案,但它是 O(n^3)。我只想知道在 O(n^2) 中是否有可能?根据问题描述不用担心空间复杂度。我很久以前就问过了。
  • @Naman 你想对上述问题有一个 O(n^2) 的时间复杂度吗?
  • 不,不是为了这个问题。我已经接受了这个答案。我要问其他问题,是链接中给出的skypscrapper问题吗? stackoverflow.com/questions/24863373/…
【解决方案2】:

让我们从验证回文的复杂性开始:

可以在 O(k) 中识别回文,其中 k 是回文 see here 的长度

然后,您需要为您的内部正方形中的每一行和每一列执行 2k 次测试。 (以回文k的长度为维度)

所以现在你有k * 2k -&gt; O(2k^2) -&gt; O(k^2)

然后你想增加整个数据集的可能搜索空间nxn这是引入第二个变量的时候

您需要在嵌套循环中迭代列 1 to (n-k) 和所有行 1 to (n-k)

所以现在你有(n-k)^2 * O(k^2) -&gt; O(n^2 * k^2)

注意:这个问题取决于多个变量

这与我建议您编写解决方案的方法相同,从小处着手,逐渐扩大

【讨论】:

  • 这是天真的蛮力方法,我知道这一点,但我想知道这是否可以通过比 O(n^2 * k^2) 更好的动态编程来完成(即 O (n^4) 在最坏的情况下)。对不起,我应该编辑我不是在寻找蛮力方法的问题。
  • 很公平,在这种情况下,您可以考虑检查每第 k 行和每列。那么您只需要在边缘行/列通过时测试行列之间的列。可能将回文测试结果存储在二维数组中
  • @Calcum 抱歉,我无法联系到您,您能否使用您建议的新算法编辑您的答案?
【解决方案3】:

我确定可能有更好的方法,而且我很确定我的逻辑是正确的,所以请从表面上看,因为它没有经过测试。

为了让示例简单,我会说 i,j 是左上角或坐标 1,1

  1 2 3 4 5 6 7 8
1 a b c d e f g f 
2 d e f g h j k q 
3 a b g d z f g f 
4 a a a a a a a a

(1,1) = a, (1,5) = e and (2,1) = d

现在您可以从检查每 k 列开始,而不是检查每一列

即当k=3

1) 创建一个2D布尔数组字符表的大小所有结果为TRUE

2) 我首先检查第 3 列 cfg 这不是回文,因此我不再需要测试第 1 列或第 2 列。

3) 因为回文测试失败将二维数组 (1,3) 中的对应结果标记为 FALSE(我知道不测试任何使用此位置的范围,因为它不是回文)

4) 接下来检查第 6 列,fjf,这是一个回文,所以我返回并测试第 5 列,ehz!= 一个回文

5) 设置 (1,5) = FALSE

6) 然后测试第 8 列然后第 7 列,

注意:您只需测试 8 列中的 5 列。

由于一行中有 k 列是回文,现在测试相应的行。在本例 3 中从底行开始,因为如果失败,它将消除大多数其他检查

7) 检查从 (3,6) fgf = 回文开始的行

8) 检查从 (2,6) jkq != 回文开始的行

9) 设置 (2,6) = FALSE

10) 检查从 (2,3) daa != palindrome 开始的列

11) 设置 (2,3) = FALSE

不需要再测试第 2 行,因为 (2,3) 和 (2,6) 都是 FALSE

希望你能理解这一点。

注意:您可能会从 k = n 开始并递减 k 直到找到结果

【讨论】:

  • 非常感谢您的帮助,但我真的无法完全理解这一切。因为,1)我需要找到最大的这样的'k',我没有得到一个。 2)我仍然觉得你的代码在最坏的情况下是 O(n^4)。我真的不能从表面上看这个。我真的不相信它的实现甚至可以达到 n=200 的值。就我而言,我必须处理 n
猜你喜欢
  • 2019-09-27
  • 2021-10-24
  • 1970-01-01
  • 2013-11-20
  • 2015-05-09
  • 1970-01-01
  • 2020-06-05
  • 2011-05-28
  • 1970-01-01
相关资源
最近更新 更多