<p>以下是问题的工作解决方案:</p>
<pre><code>def isSymmetric(A, B):
L = len(A) #assume equivalent to len(B), modifying this would be as simple as checking if len(A) != len(B), return []
la = L//2 # half-list length
Al = A[:la]
Ar = A[la:]
Bl = B[:la]
Br = B[la:]
for i in range(la):
lai = la - i #just to reduce the number of computation we need to perform
for j in range(1, lai + 1):
k = lai - j #same here, reduce computation
if Al[i] != Br[k] or Ar[k] != Bl[i]: #the key for efficient computation is here: do not proceed unnecessarily
continue
n = i #written only for the sake of clarity. i is n, and we can use i directly
m = i + j
if A[n:m] == B[L-m:L-n] and B[n:m] == A[L-m:L-n]: #possibly symmetric
if A[0:n] == B[0:n] and A[m:L-m] == B[m:L-m] and A[L-n:] == B[L-n:]:
return [n, m]
return []
</code></pre>
<p>正如你所提到的,虽然这个想法看起来很简单,但实际上是一个相当棘手的想法。然而,一旦我们看到了模式,实现就很简单了。在</p>
<p>解决方案的中心思想是这样一行:</p>
^{pr2}$
<p>所有其他行要么直接从问题语句中翻译代码,要么进行优化以提高计算效率。在</p>
<hr/>
<p>要找到解决方案,需要几个步骤:</p>
<p><strong>首先,</strong>我们需要将每个both list<code>A</code>和list<code>B</code>拆分为两个半列表(称为<code>Al</code>,<code>Ar</code>,<code>Bl</code>,和{<cd6>})。每个半列表将包含原始列表的一半成员:</p>
^{3}$
<hr/>
<p><strong>其次,</strong>为了使<strong>评估</strong>有效,这里的目标是找到我称之为<strong>枢轴索引的东西,以确定列表(索引)</em>中的<em>位置是否值得评估,以检查列表是否对称。这个<strong>轴索引</strong>是找到一个<em>有效的</em>解决方案的中心思想。所以我会尽量详细说明一下:</p>
<p>考虑<code>A</code>列表的左半部分,假设您有一个这样的成员:</p>
<pre><code>Al = [al1, al2, al3, al4, al5, al6]
</code></pre>
<p>我们可以<strong>想象</strong>对于上述列表,存在一个对应的<strong>索引</strong>列表,如下所示</p>
<pre><code>Al = [al1, al2, al3, al4, al5, al6]
iAl = [0, 1, 2, 3, 4, 5 ] #corresponding index list, added for explanation purpose
</code></pre>
<p><em>(注意:我之所以提到想象一个对应的索引列表是为了便于解释)</em></p>
<p>同样,我们可以想象其他三个列表可能有相似的索引列表。让我们分别将它们命名为<code>iAr</code>、<code>iBl</code>、和{<cd10>},它们的成员都与<code>iAl</code>相同。在</p>
<p>为了解决这个问题,列表的索引才是真正重要的。在</p>
<hr/>
<p>我的意思是:假设我们有两个参数:</p>
<ol>
<li><strong>索引</strong>(让我们给它一个变量名<code>i</code>,我将使用符号<code>^</code>表示当前的<code>i</code>)</li>
<li><strong>长度</strong>(让我们给它一个变量名<code>j</code>,我将使用符号<code>==</code>来直观地表示它的长度值)</li>
</ol>
<p>对于<code>iAl</code>中的<strong>索引</strong>元素的每个<strong>评估</strong>,则每个<strong>评估</strong>将意味着:</p>
<blockquote>
<p>Given an <strong>index</strong> value <code>i</code> and length value of <code>j</code> in <code>iAl</code>, do
something to determine if it is worth to check for symmetric
qualifications starting from that <strong>index</strong> and with that <strong>length</strong>
(Hence the name <strong>pivot index</strong> come).</p>
</blockquote>
<p>现在,让我们以一个<strong>求值</strong>为例,当<code>i = 0</code>和<code>j = 1</code>时。评估的说明如下:</p>
<pre><code>iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 0
== <-- now this has length (j) of 1
</code></pre>
<hr/>
<p>为了使那些<strong>索引</strong><code>i</code>和<strong>长度</strong><code>j</code>得到进一步的评估,那么对应的{<cd10>}必须具有相同的<em>相同的</em>项目值,但长度不相同,但索引不相同</p>
<pre><code>iBr = [0, 1, 2, 3, 4, 5]
^ <-- must compare the value in this index to what is pointed by iAl
== <-- must evaluate with the same length = 1
</code></pre>
<p>例如,对于上述情况,这是两个列表<code>Al-Br</code>的一个<em>可能的</em>“对称”排列(稍后我们将考虑另两个列表<code>Ar-Bl</code>):</p>
<pre><code>Al = [0, x, x, x, x, x] #x means don't care for now
Br = [x, x, x, x, x, 0]
</code></pre>
<p>在这一刻,值得注意的是</p>
<blockquote>
<p>It <strong>won't worth evaluating further</strong> if even the above condition is not
true</p>
</blockquote>
<p>这就是你使算法更有效的地方;也就是说,通过在所有可能的情况中只选择评估<strong>少数</strong>可能的情况。如何找到少数可能的病例?在</p>
<blockquote>
<p>By trying to find <strong>relationship between indexes and lengths</strong> of the
four lists. That is, for a given <strong>index</strong> <code>i</code> and <strong>length</strong> <code>j</code> in a
list (say <code>Al</code>), what must be the <strong>index</strong> <code>k</code> in the <strong>counterpart</strong>
list (in the case is <code>Br</code>). Length for the counterpart list need not
be found because it is the same as in the list (that is <code>j</code>).</p>
</blockquote>
<p>了解了这些之后,让我们进一步看看在<strong>评估</strong>过程中是否可以看到更多模式。在</p>
<hr/>
<p>现在考虑长度的影响(<code>j</code>)。例如,如果我们要从<strong>索引</strong><code>0</code>求值,但是长度是<code>2</code>,那么与长度为<code>1</code>时相比,对应列表需要有不同的<strong>索引</strong><code>k</code></p>
<pre><code>iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 0
===== <-- now this has length (j) of 2
iBr = [0, 1, 2, 3, 4, 5]
^ <-- must compare the value in this index to what is pointed by iAl
===== <-- must evaluate with the same length = 2
</code></pre>
<p>或者,对于上面的例子,福克斯<code>i = 0</code>和<code>y = 2</code>真正重要的是:</p>
<pre><code># when i = 0 and y = 2
Al = [0, y, x, x, x, x] #x means don't care for now
Br = [x, x, x, x, 0, y] #y means to be checked later
</code></pre>
<p>请看一下,上面的模式与<code>i = 0</code>和<code>y = 1</code>时不同,在示例中,<code>0</code><strong>值</strong>的索引位置发生了移动:</p>
<pre><code># when i = 0 and y = 1, k = 5
Al = [0, x, x, x, x, x] #x means don't care for now
Br = [x, x, x, x, x, 0]
# when i = 0 and y = 2, k = 4
Al = [0, y, x, x, x, x] #x means don't care for now
Br = [x, x, x, x, 0, y] #y means to be checked later
</code></pre>
<p>因此,<strong>长度</strong>偏移<em>,其中</em>必须检查对应列表的<strong>索引</strong>。在第一种情况下,当<code>i = 0</code>和<code>y = 1</code>,那么<code>k = 5</code>。但是在第二种情况下,当<code>i = 0</code>和{<cd34>}时,<code>k = 4</code>。因此,当我们将一个固定的<strong>索引</strong><code>j</code>(在本例中是<code>0</code>)的<strong>长度</strong><code>j</code>更改为对应列表<strong>索引</strong><code>k</code>时,我们发现了<strong>轴索引</strong>关系。在</p>
<hr/>
<p>现在,考虑长度固定的<strong>索引</strong><code>i</code>对对应列表<strong>索引</strong><code>j</code>的影响。例如,让我们将<strong>长度</strong>固定为<code>y = 4</code>,然后对于<strong>索引</strong><code>i = 0</code>,我们有:</p>
<pre><code>iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 0
========== <-- now this has length (j) of 4
iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 1
========== <-- now this has length (j) of 4
iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 2
========== <-- now this has length (j) of 4
#And no more needed
</code></pre>
<p>在上面的例子中,可以看出,我们需要计算给定的<code>i</code>和<code>j</code>的可能性,但是如果<strong>索引</strong><code>i</code>更改为长度相同的<code>j = 4</code>,则:</p>
<pre><code>iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 1
========== <-- now this has length (j) of 4
iAl = [0, 1, 2, 3, 4, 5]
^ <-- now evaluate this index (i) = 2
========== <-- now this has length (j) of 4
</code></pre>
<p>注意,我们只需要评估<strong>2</strong>的可能性。因此,<strong>指数的增加</strong><code>i</code>减少了可能要评估的案例数量!在</p>
<hr/>
<p>在找到上述所有模式之后,我们几乎找到了使算法工作所需的所有基础。但要完成这一点,我们需要找到给定的<code>Al-Br</code>对中出现的<strong>索引</strong>与同一<code>Ar-Bl</code>对中的索引</strong>之间的关系。在</p>
<p>现在,我们实际上可以看到它们只是<strong>镜像</strong>我们在<code>Al-Br</code>对中发现的关系!在</p>
<p>(IMHO,这真是太美了!所以我认为“对称”排列这个词离事实并不遥远)</em></p>
<p>例如,如果我们用<code>i = 0</code>和<code>y = 2</code>来计算<code>Al-Br</code>对</p>
<pre><code>Al = [0, y, x, x, x, x] #x means don't care for now
Br = [x, x, x, x, 0, y] #y means to be checked later
</code></pre>
<p>然后,为了使其对称,我们必须有相应的<code>Ar-Bl</code>:</p>
<pre><code>Ar = [x, x, x, x, 3, y] #x means don't care for now
Bl = [3, y, x, x, x, x] #y means to be checked later
</code></pre>
<p><code>Al-Br</code>对的<strong>索引</strong>是<strong>镜像</strong>(或对称于)<code>Ar-Bl</code>对的索引!在</p>
<hr/>
<p>因此,结合我们在上面找到的所有模式,我们现在可以找到用于评估<code>Al</code>、<code>Ar</code>、<code>Bl</code>、和{<cd6>}的<strong>轴索引。在</p>
<blockquote>
<p>We only need to check the values of the lists in the <strong>pivot index</strong>
first. If the values of the lists in the <strong>pivot indexes</strong> of <code>Al</code>, <code>Ar</code>, <code>Bl</code>, and <code>Br</code>
matches in the <strong>evaluation</strong> <strong><em>then and only then</em></strong> we need to check
for symmetric criteria (thus making the computation efficient!)</p>
</blockquote>
<hr/>
<p>将上述所有知识放入代码中,下面是要检查对称性的<code>for-loop</code>Python代码:</p>
<pre><code>for i in range(len(Al)): #for every index in the list
lai = la - i #just simplification
for j in range(1, lai + 1): #get the length from 1 to la - i + 1
k = lai - j #get the mirror index
if Al[i] != Br[k] or Ar[k] != Bl[i]: #if the value in the pivot indexes do not match
continue #skip, no need to evaluate
#at this point onwards, then the values in the pivot indexes match
n = i #assign n
m = i + j #assign m
#test if the first two conditions for symmetric are passed
if A[n:m] == B[L-m:L-n] and B[n:m] == A[L-m:L-n]: #possibly symmetric
#if it passes, test the third condition for symmetric, the rests of the elements must stay in its place
if A[0:n] == B[0:n] and A[m:L-m] == B[m:L-m] and A[L-n:] == B[L-n:]:
return [n, m] #if all three conditions are passed, symmetric lists are found! return [n, m] immediately!
#passing this but not outside of the loop means
#any of the 3 conditions to find symmetry are failed
#though values in the pivot indexes match, simply continue
return [] #nothing can be found - asymmetric lists
</code></pre>
<p>这就是对称测试!在</p>
<p><em>(好吧,这是一个相当大的挑战,我要花相当长的时间才能弄清楚)</p>