簡體   English   中英

如何檢查序列是否可以變成回文

[英]How to check if a sequence could be turned into a palindrome

我必須找到一個列表是否可以作為回文。 我的程序的第一部分對列表進行排序。

A = [0, 99, 97, 97, 99, 100, 100, 0]
# sorted:
B = [0, 0, 97, 97, 99, 99, 100, 100]

此列表可以是回文,因為它可以重新排序為:

[0, 97, 99, 100, 100, 99, 97, 0]

如果列表可以是回文,我編寫了以下代碼以返回True。

i=0
counter = 0

while i<len(B):
    if i+1 < len(B):
        if B[i]==B[i+1]:
            print(B[i],B[i+1])
            i+=2
        else:
            i+=1
            counter += 1
    else:
        i+=1

if counter<2:
    return True
return False

但是,如果我測試列表[0, 99, 97, 97, 99, 100, 100, 0, 1] ,它會進入看起來像無限循環的東西。 如何正確檢查列表是否可以成為回文?

當我們遍歷B ,我們可以使用一個集來跟蹤到目前為止哪些元素具有奇數(使用此處的集合比列表快得多):

odds = set()
for i in B:
    if i in odds:
        odds.remove(i)
    else:
        odds.add(i)

然后,如果odds的長度為0或1,則打印True 否則打印False

print len(odds) <= 1 # prints the value you're looking for

正如@Antti所指出的,如果您正在優化性能(大約20%的速度提升),可以通過在循環外部進行屬性查找來加快速度:

odds = set()
remove = odds.remove
add = odds.add
for i in B:
    if i in odds:
        remove(i)
    else:
        add(i)
print len(odds) <= 1

計算每個值的出現次數。 然后檢查奇數的數量是零還是一。 無需對列表進行排序。 這適用於任何值列表。

from collections import Counter

def can_be_palindrome(data):
    odd = (c % 2 for c in Counter(data).values())
    any(odd)  # skip first odd, if present at all
    return not any(odd)  # ensure no more odds

print(can_be_palindrome([0, 99, 97, 97, 99, 100, 100, 0]))  # only even counts, true
print(can_be_palindrome([0, 99, 97, 97, 99, 100, 100, 0, 1]))  # one odd count, true
print(can_be_palindrome([0, 99, 97, 97, 99, 100, 100, 0, 1, 2]))  # two odd counts, false
print(can_be_palindrome('abcabcd'))  # true
print(can_be_palindrome(['a', 'b', 'a', 1, 1])  # true

一個快速的(或者​​我認為):使用字典來計算odd數值。 將值存儲為字典中的鍵,如果鍵出現奇數次,則值為True ,對於偶數鍵,值為False 最后返回True,表示.values()只有0或1個True元素(也就是說,只有0或1個元素出現奇數次)。

迭代器以短路方式工作。 只要滿足第一個True ,第any將返回True ,否則它將掃描整個迭代器。 然后我們重新運行any(odd_iter) - 如果迭代器產生另一個 True(也就是奇數值),則返回True 如果第一個any用盡迭代器,那么第二個any將直接返回False 最后,我們否定此返回值並從函數返回它。

def check_palindrome_sequence(sequence):
    odds = {}
    for i in sequence:
        try:
            odds[i] ^= True
        except KeyError:
            odds[i] = True

    odd_iter = iter(odds.values())
    any(odd_iter)
    return not any(odd_iter)

A = [0, 99, 97, 97, 99, 100, 100, 0]
print(check_palindrome_sequence(A))  # True

A = [0, 99, 97, 97, 99, 100, 100, 0, 1]    
print(check_palindrome_sequence(A))  # True

A = [0, 99, 97, 97, 99, 100, 100, 0, 1, 2]
print(check_palindrome_sequence(A))  # False

Python 2.7的時間安排:

In [1]: %timeit antti(ls)
1 loops, best of 3: 128 ms per loop

In [2]: %timeit davidism(ls)
10 loops, best of 3: 103 ms per loop

In [3]: %timeit leek(ls)
10 loops, best of 3: 42.1 ms per loop

所有3的數據都相同:

ls = list(range(100000))
ls *= 2
ls += [ 1, 2 ]
random.shuffle(ls)

在Python 3上的時間,數據相同:

In [1]: %timeit leek(ls)
10 loops, best of 3: 37.4 ms per loop

In [2]: %timeit antti(ls)
10 loops, best of 3: 89.3 ms per loop

In [3]: %timeit davidism(ls)
10 loops, best of 3: 52 ms per loop

韭菜是完全隨機的最佳整體。 nettux的答案是以二次方式放慢速度,必須花一分鍾才能獲得100000 * 2 + 2個元素,而且我沒有耐心等待時間。

對於小的值,它是一個回文,它幾乎是韭菜的勝利

In [1]: %timeit leek(ls)                         
100000 loops, best of 3: 2.21 µs per loop

In [2]: %timeit antti(ls)
100000 loops, best of 3: 5.52 µs per loop

In [3]: %timeit davidism(ls)
100000 loops, best of 3: 7.45 µs per loop

這里有一個簡單的方法,如果數字也需要按順序排列(如[1,1,2,2,3]可行,但不是[1,1,2,3,3] ),它只是要求每2個字符拆分排序列表

def palindrome( input ):
    B = sorted(input)

    #Get every even index
    firstPart = B[::2]
    #Get every odd index
    secondPart = B[1::2]
    #Fix for if there's an odd number of indexes
    if len(secondPart) < len(firstPart):
        secondPart.append( B[-1] )
    #Return true or false
    return firstPart==secondPart


print palindrome( [0, 99, 97, 97, 99, 100, 0] )
#True
print palindrome( [0, 99, 97, 97, 99, 100, 100, 0] )
#True
print palindrome( [0, 94, 97, 97, 99, 100, 0] )
#False

也縮短了一點,但這種方式不太可讀:

def palindrome( B ):
    B=sorted(B)
    if len(B)%2:
        B+=[B[-1]]
    return B[::2]==B[1::2]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM