![](/img/trans.png)
[英]How do I write a Python code to check if the given sequence is a palindrome or not?
[英]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.