lintcode刷題(Python)(2)
11! = 39916800,因此應該返回 2
一開始也沒多想,隨便設計了一個演算法,迴圈遍歷,但時間複雜度不滿足,GG了:
class Solution: """ @param: : An integer @return: An integer, denote the number of trailing zeros in n! """ def trailingZeros(self, n): # write your code here, try to do it without arithmetic operators. count = 0 while n - 1 != 0: i = n while i % 10 == 0: i = i / 10 count += 1 while i % 5 == 0 and i % 10 != 0: i = i / 5 count += 1 n = n - 1 return count
後來仔細想了一下,要求0的個數,就要考慮什麼時候會出現0
只要一個數可以被5整除,肯定就會出現0,如果被25整除,就會出現2個0,125會出現3個0
所以可以這樣:
假設要求一個很大的數的階乘0的個數,
直接將它除以5,得到了小於它的數中,可以被5整除的數的個數。
將它除以25,得到了小於它的數中,可以被25整除的數的個數........
但是要不要除以125、625、5的n次方呢?只要它大於它們,肯定要除的。
所以先要判斷出來n到底等於幾,而且這個很簡單。
綜上,程式碼如下:
class Solution: """ @param: : An integer @return: An integer, denote the number of trailing zeros in n! """ def trailingZeros(self, n): # write your code here, try to do it without arithmetic operators. count5 = 0 base5 = 5 result = 0 while n > base5: base5 *= 5 count5 += 1 for i in range(1, count5+1): result = result + int(n / (5 ** i)) return result
Substring Anagrams
Given a string s
and
a non-empty string p
, find all the start indices
of p
's anagrams in s
.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 40,000.
The order of output does not matter.
樣例Given s = "cbaebabacd"
"abc"
return [0, 6]
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
這道題的意就是判斷p在s中出現的位置,當然只要p中所有的字母都出現了就行,不用按照順序來。
一開始寫了個演算法,但是是缺陷的,滿足不了時間複雜度,後面我會改進,先貼出來:
class Solution:
# @param {string} s a string
# @param {string} p a non-empty string
# @return {int[]} a list of index
def findAnagrams(self, s, p):
# Write your code here
#一個一個遍歷s,如果當前遍歷的字母在p中存在,則p出棧該字母表,往下移動,繼續判斷。
lengthP=len(p)
result=[]
for i in range(0,len(s)-lengthP+1):
listP=list(p)
char=s[i]
j=i
while char in listP:
listP.remove(char)
if listP==[]:
result.append(i)
break
char = s[j+1]
j=j+1
return result
為什麼會出現時間複雜度不滿足呢?原因是這個演算法太“ 乖”了,它只會一個一個向前遍歷s中的字母。
考慮這樣一種極端情況,s是由 1萬個a+一個b+1萬個a 組成的字串,p是一萬個a。在遍歷時,i是s的下標。i=0時,滿足條件(都是一萬個a),但是當i=1時,會遇到“b”,此時前面的所有情況,其實都不用考慮了,因為b在p中根本不存在!!所以我們直接可以跳過9千多個字元,直接將i置為b的下一個字母的座標!這樣時間複雜度一下子就降下來了。
這是改進後的演算法:
class Solution:
# @param {string} s a string
# @param {string} p a non-empty string
# @return {int[]} a list of index
def findAnagrams(self, s, p):
# Write your code here
lengthP = len(p)
result = []
i = 0
while i<=len(s)-lengthP:
listP = list(p)
char = s[i]
j = i
while char in listP:
listP.remove(char)
if listP == []:
result.append(i)
break
char = s[j + 1]
j = j + 1
if char not in p:
i=j #當char在p中不存在時,直接從該char的下一個字母開始判斷
break
i+=1
return result