leetcode python實現

53 最大子序和

給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。

示例:

輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。

解:


    class Solution:
        def maxSubArray(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """        
            count = -100000000000000000000
            maxlen = [0]*len(nums)
            for i in range(len(nums)):
                for j in range(i,len(nums)):
                    maxlen[i] += nums[j]
                    if maxlen[i]>count:
                        count = maxlen[i]
                    if maxlen[i] <0:
                        break
            return count     

簡寫爲:

    class Solution:
        def maxSubArray(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """        
            count = nums[0]
            for i in range(len(nums)):
                maxlen = 0
                for j in range(i,len(nums)):
                    maxlen += nums[j]
                    if maxlen>count:
                        count = maxlen[i]
                    if maxlen <0:
                        break
            return count   

但這樣其實沒有簡單 複雜度高。

當我們加上一個正數時,和會增加;當我們加上一個負數時,和會減少。如果當前得到的和是個負數,那麼這個和在接下來的累加中應該拋棄並重新清零,不然的話這個負數將會減少接下來的和。

    class Solution:
        def maxSubArray(self, num):
            dp = num[0]
            max_s = dp
            for i in range(1, len(num)):
                if dp <= 0:
                    dp = num[i]
                else:
                    dp += num[i]
                if dp > max_s:
                    max_s = dp
            return max_s

198 打家劫舍

假設當前已經肆虐過了前i個房子(0…i-1),且rob[i]是搶劫了下標爲i的房子時的最大收益,pass[i]是不搶劫下標爲i的房子時的最大收益,那麼可以得到狀態轉移方程:

參考 http://mzorro.me/2016/03/15/leetcode-house-robber/

狀態方程:

    rob[i] = nums[i] + pass[i-1]
    pass[i] = max(rob[i-1], pass[i-1])

最重要的是先確定狀態方程

    class Solution:
        def rob(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if len(nums)<=0:
                return 0
            rob,passc = [0]*len(nums),[0]*len(nums)
            rob[0]=nums[0]
            for i in range(1,len(nums)):
                rob[i] = nums[i]+passc[i-1]
                passc[i] = max(rob[i-1],passc[i-1])
            return max(max(passc),max(rob))

也可以寫爲:

    class Solution(object):
        def rob(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if nums == []:
                return 0
            dp=[0]*(len(nums)+1)
            dp[1] = nums[0]
            for i in range(2,len(nums)+1):
                dp[i] = max(dp[i-1],nums[i-1]+dp[i-2])  #因爲有涉及i-2,所以這裏dp向量維度多1
            return dp[len(nums)]

413. 等差數列劃分

如果一個數列至少有三個元素,並且任意兩個相鄰元素之差相同,則稱該數列爲等差數列。
例如,以下數列爲等差數列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下數列不是等差數列。
1, 1, 2, 5, 7
數組 A 包含 N 個數,且索引從0開始。數組 A 的一個子數組劃分爲數組 (P, Q),P 與 Q 是整數且滿足 0<=P<Q<N 。
如果滿足以下條件,則稱子數組(P, Q)爲等差數組:
元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。並且 P + 1 < Q 。
函數要返回數組 A 中所有爲等差數組的子數組個數。
示例:
A = [1, 2, 3, 4]
返回: 3, A 中有三個子等差數組: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。

解析:

參考 http://www.cnblogs.com/grandyang/p/5968340.html

要點在於 子數組個數怎麼解。

我的第一種解法,三重循環,複雜度太高:

    class Solution(object):
        def numberOfArithmeticSlices(self, A):
            """
            :type A: List[int]
            :rtype: int
            """
            n = len(A)
            count=0
            for i in range(2, n):
                for j in range(n - i):  # 考慮所有連續的長度爲i+1的子串,s[j....j+i]
                    temp = 1
                    for k in range(j,j+i-1):
                        if A[k+2] - A[k+1] != A[k+1] - A[k]:
                            temp = 0
                            break
                    count += temp
            return count

用動態規劃的解法:這裏有規律,如果知道了是等差數列,比如1,2,3 再加入下一個,比如2,3,4,也是等差,在已知前一個是等差的基礎上,這裏是加1了。

    class Solution:
        def numberOfArithmeticSlices(self, A):
            """
            :type A: List[int]
            :rtype: int
            """  
            dp = [0]*len(A)
            res=0
            for i in range(2,len(A)):
                if A[i]-A[i-1] == A[i-1]-A[i-2]:
                    dp[i] = dp[i-1]+1
                res+=dp[i]
            return res

152. 乘積最大子序列

給定一個整數數組 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。

示例 1:

輸入: [2,3,-2,4]
輸出: 6
解釋: 子數組 [2,3] 有最大乘積 6。
示例 2:

輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能爲 2, 因爲 [-2,-1] 不是子數組。

這題初看,以爲是413等差數列劃分的解法,但不太一樣,因爲有正負,沒有一個衡量標準。
看了解答後,發現要設置最大最小兩個參數,因爲帶負號的最小,只要遇到新的一個負號,就可能會變成最大。

    class Solution(object):
        def maxProduct(self, A):
            mmax,mmin = [0]*len(A),[0]*len(A)
            mmax[0],mmin[0],res = A[0],A[0],A[0]
            for i in range(1,len(A)):
                mmax[i] = max(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
                mmin[i] = min(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
                res = max(res,mmax[i])
            return res

695. 島嶼的最大面積

給定一個包含了一些 0 和 1的非空二維數組 grid , 一個 島嶼 是由四個方向 (水平或垂直) 的 1 (代表土地) 構成的組合。你可以假設二維矩陣的四個邊緣都被水包圍着。找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積爲0。)
示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,1,1,0,1,0,0,0,0,0,0,0,0],
 [0,1,0,0,1,1,0,0,1,0,1,0,0],
 [0,1,0,0,1,1,0,0,1,1,1,0,0],
 [0,0,0,0,0,0,0,0,0,0,1,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,1,1,0,0,0,0]]
對於上面這個給定矩陣應返回 6。注意答案不應該是11,因爲島嶼只能包含水平或垂直的四個方向的‘1’。
示例 2:
[[0,0,0,0,0,0,0,0]]
對於上面這個給定的矩陣, 返回 0。

用廣度優先搜索dfs解:
注意:這裏不需要一個flag,直接把grid設置爲0即可,因爲grid是連通域,掃描過一次,之後不會再第二次用到,所以可以設成0.

    def maxAreaOfIsland(grid):
        count=0
        def dfs(grid,i,j):
            if i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]==0:
                return 0
            grid[i][j]=0
            return dfs(grid,i-1,j) + dfs(grid,i+1,j) + dfs(grid,i,j+1) + dfs(grid,i,j-1) +1
    
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j]==1:
                    count = max(dfs(grid,i,j),count)
        return count
    
    A = [[0,0,1],[1,0,1],[1,1,0]]
    
    print(maxAreaOfIsland(A))

874. 模擬行走機器人

這題看了答案,沒想出來。
自己重寫了一遍,值得注意的是,如果用數組[],不用tuple()的話,會超出時間限制,不知爲何。

    class Solution:
        def robotSim(self, commands, obstacles):
            i = j = mx = d = 0
            move, obstacles = [(0, 1), (-1, 0), (0, -1), (1, 0) ], set(map(tuple, obstacles))
            for command in commands:
                if command == -2: d = (d + 1) % 4
                elif command == -1: d = (d - 1) % 4
                else:
                    x, y = move[d]
                    while command and (i + x, j + y) not in obstacles:
                        i += x
                        j += y
                        command -= 1
                mx = max(mx, i ** 2 + j ** 2)
            return mx

以下用[]會超出時間限制:

    class Solution(object):
        def robotSim(self, commands, obstacles):
            """
            :type commands: List[int]
            :type obstacles: List[List[int]]
            :rtype: int
            """
            i = j = d = res= 0
            move = [[0,1],[-1,0],[0,-1],[1,0]]
    
            for com in commands:
                if com == -2:
                    d = (d+1)%4
                elif com == -1:
                    d = (d-1)%4
                else:
                    x,y = move[d] 
                    while com and [i+x,j+y] not in obstacles:
                        i += x
                        j += y
                        com -= 1
                res = max(res, i**2 + j**2) 
            return res

104. 二叉樹的最大深度

給定一個二叉樹,找出其最大深度。

二叉樹的深度爲根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定二叉樹 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

這題要好好看看,最大深度就是深度優先搜索dfs,用遞歸!;還可以層次遍歷,用bfs的方法也可以得到層數。

dfs遞歸:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            if root==None:
                return 0
            return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right))

複雜度分析:

時間複雜度:我們每個結點只訪問一次,因此時間複雜度爲O(N),其中N是結點的數量。

空間複雜度:在最糟糕的情況下,樹是完全不平衡的,例如每個結點只剩下左子結點,遞歸將會被調用N次(樹的高度),因此保持調用棧的存儲將是O(N)。
但在最好的情況下(樹是完全平衡的),樹的高度將是log(N)。因此,在這種情況下的空間複雜度將是O(log(N))

麻煩一點的bfs:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            if root == None:
                return 0
            res = 0
            q = [root]
            while q:
                res+=1
                for i in range(len(q),0,-1):
                    t = q[0]
                    q.pop(0)
                    if t.left:
                        q.append(t.left)
                    if t.right:
                        q.append(t.right)
            return res

官方題解,迭代法:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """ 
            stack = []
            if root is not None:
                stack.append((1, root))
            
            depth = 0
            while stack != []:
                current_depth, root = stack.pop()   #這裏的current_depth很巧妙,不是每次讓current_depth+=1,因爲這樣就錯了,難點所在。
                if root is not None:
                    depth = max(depth, current_depth)
                    stack.append((current_depth + 1, root.left))
                    stack.append((current_depth + 1, root.right))
            
            return depth

谷歌一題

題目:

由輸入字符串生成輸出字符串數組, 實現linux指令echo的功能
1:輸入:a{1,2,3}{4,3,2}          
輸出:     [a14, a23, a32]
2:輸入:{1,2,3}a{4,5,6}{7,8,9}
輸出:[1a47, 2a58, 3a69]
3:輸入:{a,d,s}{g,k,l}{j,k,l}f
輸出:[agjf, dkkf, sllf]

思路:

{1,2,3}a{4,5,6}{7,8,9}
Step1: 按照{進行分割,會分爲四組,確保最終輸出的字符串長度正確
“”,  “1,2,3}a”,  “4,5,6}”,    “7,8,9}”
Step2: 當上述例子中a出現在中間或者最右時可能分割不正確,進行糾正:
1)     去掉右括號,如果右括號不是出現在最後一個字符,將這個字符串拆成兩個,例如,1,2,3}a”按照“}”的位置拆分爲”1,2,3”和”a”
2)     忽略拆分的空字符串
Step3:拆分得到:“1,2,3”,  “a”,  “4,5,6”,    “7,8,9”
將結果存儲到一個二維數組。行爲最後輸出字符串要拼接的元素個數,列爲{}中的元素個數,本例中分別爲 4和3
Step4:將每行數組按照列的位置組合到一起,組成新的數組輸出:
[1a47, 2a58, 3a69]

解答:

    def expand(expression):
        rawWord = expression.split('{')
        l = 1
        point = 0
        word = [[0 for col in range(len(rawWord))] for row in range(len(rawWord))]
        for i in range(len(rawWord)):
            if len(rawWord[i]) < 1:
                continue
            if rawWord[i][len(rawWord[i])-1] != '}':
                tmp = rawWord[i]
                if rawWord[i].index('}') == -1:
                    word[point] = [0]
                    word[point][0] = rawWord[i]
                    point += 1
                else:
                    rawWord[i] = rawWord[i][0:rawWord[i].index('}')].replace('}','')
                    word[point] = rawWord[i].split(',')
                    point += 1
                    word[point] = [0]
                    word[point][0] = tmp[tmp.index('}')+1:]
                    point += 1
            else:
                rawWord[i] = rawWord[i].replace('}','')
                word[point] = rawWord[i].split(',')
                point += 1
                if l==1 and l<len(word[point-1]):
                    l = len(word[point-1])
        answer = [0]*l
        for j in range(l):
            answer[j] = []
            for i in range(len(rawWord)):
                if word[i] == None:
                    continue
                elif len(word[i]) == 1:
                  answer[j] += word[i][0]
                else:
                    answer[j] += word[i][j]
        ans = [0]*l
        for j in range(l):
            ans[j] = ''.join(answer[j])
        return ans
    c = '{3,5,6}{7,8,9}{a,b,c}{3,4,5}a'
    a = '{3,5,6}{7,8,9}a{a,b,c}{3,4,5}'
    ans = expand(a)
    print(ans)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章