leetcode python 2-11

說明:自己思考以及和別人對比,參考對比程序來源

包含 2 - 11 題

002、單向鏈表兩數相加

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        current = ListNode(0)
        p = current
        value = 0

        while l1 or l2:

            if l1:
                value = value + l1.val
                l1 = l1.next

            if l2:
                value = value + l2.val
                l2 = l2.next

            # current.var = value % 10
            var = value % 10
            value = value / 10
            current.next = ListNode(var)
            current = current.next

        if value:
            # current.var = value
            current.next = ListNode(value)

        return p.next

if __name__ == '__main__':
    a, a.next, a.next.next = ListNode(2), ListNode(4), ListNode(3)
    b, b.next, b.next.next = ListNode(5), ListNode(6), ListNode(4)
    result = Solution().addTwoNumbers(a, b)
    print "%d -> %d -> %d " %(result.val , result.next.val , result.next.next.val)

這個題主要注意以下問題:要考慮兩個鏈表不同長度的相加;第一個頭結點不保留數據,返回p.next;

003、最大不重復的子串

Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

以下是自己的答案,用了兩個for循環,還是復雜了點,最后一個測試超時
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        length_max = 0

        for i in range(0,len(s)):
            mystr , length = self.search(s[i:])
            if length > length_max:
                length_max = length
        return length_max



    def search(self,s):
        i = 0
        while s[i] not in s[0:i]:
            i += 1
            if i == len(s):
                break

        length = i
        mystr = s[0:i]
        #print mystr
        return mystr,length


if __name__ == '__main__' :

    s = Solution()
    length_max1 = s.lengthOfLongestSubstring('abcdefgabc')
    print length_max1
別人的答案 48.5%
class Solution:
    # @return an integer
    def lengthOfLongestSubstring(self, s):
        longest, start, visited = 0, 0, [False for _ in xrange(256)]
        for i, char in enumerate(s):
            if visited[ord(char)]:
                while char != s[start]:
                    visited[ord(s[start])] = False
                    start += 1
                start += 1
            else:
                visited[ord(char)] = True
            longest = max(longest, i - start + 1)
        return longest

if __name__ == "__main__":
    print Solution().lengthOfLongestSubstring("abcabcbb")

004、Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        result = []
        i = 0
        j = 0
        median, flag = (len(nums1) + len(nums2))//2, (len(nums1) + len(nums2))%2
        while i < len(nums1) and j < len(nums2):
            if nums1[i] < nums2[j]:
                result.append(nums1[i])
                i += 1
            else:
                result.append(nums2[j])
                j += 1
        result += nums1[i:]
        result += nums2[j:]
        if flag == 1:
            return (result[median] + result[median]) * 0.5
        if flag == 0:
            return (result[median - 1] + result[median]) * 0.5


if __name__ == '__main__':
    print Solution().findMedianSortedArrays([1, 3, 5, 7], [2, 4, 6])
    print Solution().findMedianSortedArrays([1, 2], [3,4])

這個題目反應出基礎功,由于快速過了一遍數據結構和算法,將兩個排好序的序列重新組合這么簡單的問題居然會無從下手,而又覺得特別熟悉,其實在歸并排序中就有出現,而這邊也是完全借用歸并排序的思想。其實上述有個明顯的缺點就是將整個數組排序了,實際上只需要排序到指定位置即可。

運行時間 108ms 超過了60%
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        len1, len2 = len(nums1), len(nums2)
        if (len1 + len2) % 2 == 1: 
            return self.getKth(nums1, nums2, (len1 + len2)/2 + 1)
        else:
            return (self.getKth(nums1, nums2, (len1 + len2)/2) + \
                    self.getKth(nums1, nums2, (len1 + len2)/2 + 1)) * 0.5

    def getKth(self, A, B, k):
        m, n = len(A), len(B)
        if m > n:
            return self.getKth(B, A, k)

        left, right = 0, m    
        while left < right:
            mid = left + (right - left) / 2
            if 0 <= k - 1 - mid < n and A[mid] >= B[k - 1 - mid]:
                right = mid
            else:
                left = mid + 1

        Ai_minus_1 = A[left - 1] if left - 1 >= 0 else float("-inf")
        Bj = B[k - 1 - left] if k - 1 - left >= 0 else float("-inf")

        return max(Ai_minus_1, Bj)

上述為別人的思路,運行時間95ms。

005 Longest Palindromic Substring 最大回文字符串

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        length = len(s)
        maxlen, maxL, maxR = 0, 0, 0
        for i in range(length):
            start = i    #考慮為偶數情況
            end = i + 1
            while start >= 0 and end <= length - 1:
                if s[start] == s[end]:
                    if end - start + 1 > maxlen:
                        maxlen = end - start + 1
                        maxL = start
                        maxR = end
                    start -= 1
                    end += 1
                else:
                    break
            start = i - 1   #考慮為奇數情況
            end = i + 1
            while start >= 0 and end <= length - 1:
                if s[start] == s[end]:
                    if end - start + 1 > maxlen:
                        maxlen = end - start + 1
                        maxL = start
                        maxR = end
                    start -= 1
                    end += 1
                else:
                    break
        return s[maxL:maxR+1]
        
if __name__ == '__main__':
    solution = Solution()
    print solution.longestPalindrome('abbacd')

上面的程序運行效率不是很高,只優于41%的提交。
是否能把所有的情況全部轉換為奇數處理?Manacher算法,且這個算法求最長回文子串的時間復雜度是線性O(N)的。參考

def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        def preProcess(s):
            if not s:
                return ['^', '$']
            T = ['^']
            for c in s:
                T +=  ['#', c]
            T += ['#', '$']
            return T

        T = preProcess(s)
        P = [0] * len(T) 
        center, right = 0, 0
        for i in xrange(1, len(T) - 1):
            i_mirror = 2 * center - i
            if right > i:
                P[i] = min(right - i, P[i_mirror])
            else:
                P[i] = 0

            while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
                P[i] += 1

            if i + P[i] > right:
                center, right = i, i + P[i]       
        
        max_i = 0
        for i in xrange(1, len(T) - 1):
            if P[i] > P[max_i]:
                max_i = i
        start = (max_i - 1 - P[max_i]) / 2
        return s[start : start + P[max_i]]

6、 ZigZag Conversion

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1:
            return s
        str1 = ''
        j, flag = 0, 0
        T = ['' for i in range(numRows)]

        for i in range(len(s)):
            if flag == 0:
                T[j] += s[i]
                j += 1
                if j == numRows:
                    flag = 1
                    j -= 2
            else:
                #p[i] = j
                T[j] += s[i]
                j -= 1
                if j == -1:
                    flag = 0
                    j += 2

        for i in range(numRows):
            str1 += T[i]
        return str1

if __name__ == '__main__':
    solution = Solution()
    print solution.convert('abc',2)

上述算法 思路主要是:0123432101234321。
運行結果出來一瞬間真是崩了,216ms,只勝于10%,可能原因一是算法確實沒別人好,二是字符串操作可能會帶來開銷。

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1:
            return s
        step, zigzag = 2 * numRows - 2, ""
        for i in xrange(numRows):
            for j in xrange(i, len(s), step):
                zigzag += s[j]
                if 0 < i < numRows - 1 and j + step - 2 * i < len(s):
                    zigzag += s[j + step - 2 * i]
        return zigzag

if __name__ == "__main__":
    print Solution().convert("PAYPALISHIRING", 3)

該算法優于40%,還是不夠好

7、Reverse digits of an integer

Example1: x = 123, return 321
Example2: x = -123, return -321

這個問題需要注意的有兩個問題,一是可能是負數,二是考慮是否越界,假設為有符號32bit。
反轉一般有兩種常用解決方式,一是以整數方式,除10取余,二是利用字符串自帶的反轉功能,str1[::-1]。

class Solution(object):
    def reverse(self, x):  #該方法更優
        """
        :type x: int
        :rtype: int
        """
        if x < 0:
            return -self.reverse(-x)

        result = 0
        while x:
            result = result * 10 + x % 10
            x /= 10
        return result if result <= 0x7fffffff else 0  # Handle overflow.

    def reverse2(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x < 0:
            x = int(str(x)[::-1][-1] + str(x)[::-1][:-1])
        else:
            x = int(str(x)[::-1])
        x = 0 if abs(x) > 0x7FFFFFFF else x
        return x

    def reverse3(self, x):
        """
        :type x: int
        :rtype: int
        """
        s = cmp(x, 0)
        r = int(`s * x`[::-1])
        return s * r * (r < 2 ** 31)

字符串反轉有以下兩種常用方法:

  • 使用[::-1]:
    s = 'python'
    print s[::-1]

  • 使用reverse()方法:
    l = list(s)
    l.reverse() #不返回,但是原列表已經反轉
    print ''.join(l)

8、String to Integer (atoi)

這個題確實有很多細節需要考慮,一開始做的時候只考慮了字符串中間有字母,以及首位可能為'-',發現還有可能首位為‘+’和一個或多個空格。該題還有一個特殊就是'12a'也能出結果12,就是是逐個判斷

class Solution(object):
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        result, flag = 0, 1
        if len(str) == 0:
            return 0
        if len(str) == 1 and str not in '0123456789':
            return 0
        if str[0] == ' ':
            return self.myAtoi(str[1:])
        
        for i in range(0,len(str)):
            if i == 0 and str[i] not in '-+0123456789':
                return 0
            if i>0 and str[i] not in '0123456789':
                return 0
        
        for c in str:            
            if c == '-':
                flag = -1
                continue
            if c == '+':
                continue
            num = ord(c) - ord('0')
            result = result*10 + num
            
        return result*flag

以上是初步代碼,還有很多需要改善,邏輯關系沒有劃分很清楚,沒有考慮到越界,遞歸調用看似簡便但開銷大,使用兩個循環,略顯臃腫。

class Solution(object):
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        result, i, flag = 0, 0, 1
        if len(str) == 0:
            return 0
        while str[i] == ' ':
            i += 1
        if str[i] == '-':
            flag = -1
            i += 1
        elif str[i] == '+':
            i += 1
        
        while i<len(str) and str[i] >= '0' and str[i] <= '9':
            result = result*10 + ord(str[i]) - ord('0')
            i += 1
            if result > 2147483647:
                break
        
        result *= flag
        if result >= 2147483647:
            return 2147483647
        if result <= -2147483648:
            return -2147483648
        
        return result
        
if __name__ == '__main__':
    solution = Solution()
    print solution.myAtoi('1')

9. Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.

class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0:
            return False
            
        l = len(str(x)) - 1
        while l > 0:
            if x % 10 != x // 10**l:
                return False
            x = x // 10
            l -= 1
            x = x % 10**l
            l -= 1
            
        return True
        
if __name__ == '__main__':
    solution = Solution()
    print solution.isPalindrome(12313214)

算比較簡單,第一次提交 81% ,第二次就 69% 第三次 21% 。也是很惶恐,本來開開心心。
趕緊找來別人的看看

class Solution:
    # @return a boolean
    def isPalindrome(self, x):
        if x < 0:
            return False
        copy, reverse = x, 0
        
        while copy:
            reverse *= 10
            reverse += copy % 10
            copy /= 10
        
        return x == reverse

if __name__ == "__main__":
    print Solution().isPalindrome(12321)
    print Solution().isPalindrome(12320)
    print Solution().isPalindrome(-12321)

這個看起來更優化點,一測試 30%,已經不知道說啥。

10. Regular Expression Matching

Implement regular expression matching with support for '.' and '*'.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.

http://www.cnblogs.com/zuoyuan/p/3781773.html
最后一個‘*’一定不要下意識認為是正則表達式中匹配0或任意個字符,這里是匹配前面出現的字符,可以是不匹配(及匹配0次也可以重復)

class Solution:
    # @return a boolean
    def isMatch(self, s, p):
        if len(p)==0: return len(s)==0
        if len(p)==1 or p[1]!='*':
            if len(s)==0 or (s[0]!=p[0] and p[0]!='.'):
                return False
            return self.isMatch(s[1:],p[1:])
   
        else:
            i=-1; length=len(s)
            while i<length and (i<0 or p[0]=='.' or p[0]==s[i]):
                if self.isMatch(s[i+1:],p[2:]): return True
                i+=1
            return False

算法題理清思路很重要:

isMatch(s, p):

1. 當前p為0時,若s也是0時,則返回true,否則為false
2. 當前p不為0時,
  1) p的下一個不是'*'時
    if: 當前s與p匹配,
      則表明到此都是匹配的,只需要檢查isMatch(s + 1, p + 1)
    else:
      返回false
  2) p的下一個是'*'時,
    while: 當前s與p匹配,即表明至此也是匹配的
      if: 當前s與下一個p也都匹配,即isMatch(s, p + 2),則返回true
      else: s++
    此時,當前s與當前p已經不匹配了(之前s都是匹配的),則檢測下一個模板isMatch(s, p + 2)

上面是用遞歸方法,也有人說用動態規劃比較好,待思考。http://www.cnblogs.com/flowerkzj/p/3726667.html

11、Container With Most Water

給定n個數,a1,a2,...,an.在坐標上的位置為(i,ai),求其中兩個點到X軸的線段與x軸圍成的面積最大。

思路:
1、暴力法:用兩個for循環,超時了,看來還是得動腦子。
2、貪心法,從兩邊向中間夾逼,兩個指針指向列表兩端,當左邊高度<右邊時,制約在左邊,右邊往左移肯定找不到更大的,應該左邊往右移,反之也成立。
但注意到,每次都會比較一次,但是當右移或左移的數比原來小時,沒有必要進行計算,因為肯定會比原來結果小,如何優化代碼。

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        length = len(height) 
        if length < 2:
            return -1
        
        left = 0
        right = length - 1
        max_contain = 0
        while left < right:
            max_contain = max(max_contain, min(height[left] , height[right]) * (right - left))
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1                                     
        return max_contain
                    
            
if __name__ == '__main__':
    solution = Solution()
    print solution.maxArea([1,3,56,57,8])

優化后,擊敗92%,欣慰。

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        length = len(height) 
        if length < 2:
            return -1
        
        left = 0
        right = length - 1
        max_contain = 0
        while left < right:
            max_contain = max(max_contain, min(height[left] , height[right]) * (right - left))
            if height[left] < height[right]:
                j = left
                left += 1
                
                while height[left] <= height[j] and left < right: #若<原來的數,直接下一個,算都不用算
                    left += 1
            else:
                j = right
                right -= 1
                
                while height[right] <= height[j] and left < right:
                    right -= 1                                       
        return max_contain                               
if __name__ == '__main__':
    solution = Solution()
    print solution.maxArea([1,2])
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,704評論 0 23
  • NSArray內存布局 順序存儲結構與鏈式存儲結構的比較(也可以說的順序表與鏈表的比較
    iOS_愛OS閱讀 249評論 0 0
  • Ⅰ、概念的到來主要源于感受,其次源于詞匯積累。一個概念可以解釋另外一個概念,概念之間可以相互關聯,但卻永遠無法用概...
    奶香味旅途閱讀 506評論 0 3
  • 江心映著明月 有了天涯與共的一瞬 秋水映著長天 有了魚鳥齊飛的一刻 瞳孔映著誰 方有相濡以沫的一生 ——滄藍
    一毫米閱讀 280評論 0 2