1. 程式人生 > >lintcode刷題(Python)(2)

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"

 p = "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