1. 程式人生 > >Python 刷題(想練python的可以對著刷一刷,持續更新)

Python 刷題(想練python的可以對著刷一刷,持續更新)

Surrounded Regions


這道題要求將完全由‘X’包圍的‘O’全部置為‘X’,也就是將由‘X’包裹的‘O’連通塊全部置為‘X’的意思。在矩陣中找連通塊,直接進行bfs就可以,如果有任意的一個‘O’到了邊界處,那麼這個‘O’連通塊就沒有被‘X’完全包圍,否則則將全部的‘O’置為‘X’。剛開始可能是座標計算手賤了把X和Y打錯了,TLE了,後來改了就過了。

好久沒寫這種型別的bfs,一時半會兒手生,弱死的節奏啊。

class Solution:
    # @param board, a 9x9 2D array
    # Capture all regions by modifying the input board in-place.
    # Do not return any value.
    def solve(self, board):
        
        if board==None:
            return
        
        n = len(board)
        if n==0:
            return
        m = len(board[0])
        
        vis = [None]*len(board)
        for i in range(len(board)):
            vis[i] = [0]*len(board[0])
        
        for i in range(n):
            for j in range(m):
                if board[i][j]=='O' and vis[i][j]==0:
                    self.check(board, vis, i, j)
        
    def check(self, board, vis, x, y):
        n = len(board)
        m = len(board[0])
        
        dir = [(1, 0), (-1, 0), (0, 1), (0, -1)]
        
        flag = True
        q = []
        q.append((x, y))
        vis[x][y] = 1
        while len(q)!=0:
            curx, cury = q[0]
            q.remove(q[0])
            
            for i in range(4):
                tx = curx+dir[i][0]
                ty = cury+dir[i][1]
                if tx==-1 or tx==n or ty==-1 or ty==m:
                    flag = False
                    continue
                
                if board[tx][ty]=='O' and vis[tx][ty]==0:
                    q.append((tx, ty))
                    vis[tx][ty] = 1
                    
        if flag==False:
            return
        
        q = []
        q.append((x, y))
        vis[x][y]=2
        while len(q)!=0:
            curx, cury = q[0]
            q.remove(q[0])
            
            board[curx][cury] = 'X'

            for i in range(4):
                tx = curx+dir[i][0]
                ty = cury+dir[i][1]
                
                if tx==-1 or tx==n or ty==-1 or ty==m:
                    pass
                else:
                    if board[tx][ty]=='O' and vis[tx][ty]!=2:
                        q.append((tx, ty))
                        vis[tx][ty] = 2

Distinct Subsequences

典型的動態規劃,給定串S和T,問S中有多少種可能的子序列使得該子序列正好和T相同。比如說S='aacb',T='ab',那麼結果就是2.

這種直觀感覺可以通過依次遞推上去的,或者說是具有最優子結構性質的問題都是通過動態規劃的方法來求解。定義狀態dp[i][j]表示T的子串T[0, i]在S子串S[0, j]出現的合法的次數,那麼狀態轉移方程如下:

if T[i] != S[j],dp[i][j]=dp[i][j-1]

else if T[i] == S[j], dp[i][j] = dp[i][j-1] + dp[i-1][j-1]

注意初始化dp[0][j]=1,也就是說任意的空串都在S[0,j]中出現一次。

按照上面的狀態轉移方程寫出程式碼就行了。

class Solution:
    # @return an integer
    def numDistinct(self, S, T):
        if S==None or T==None:
            return 0
        if len(S)==0 or len(T)==0:
            return 0
        S = '.' + S
        T = '.' + T
        dp = [[0]*len(S) for i in range(len(T))]
        for i in range(len(S)):
            dp[0][i] = 1
        for i in range(1, len(T)):
            for j in range(i, len(S)):
                dp[i][j] = dp[i][j-1]
                if T[i] == S[j]:
                    dp[i][j] += dp[i-1][j-1]
        return dp[len(T)-1][len(S)-1]

#s = Solution()
#print(s.numDistinct('rabbbit', 'rabbit'))
#print(s.numDistinct('abc', 'ac'))
#print(s.numDistinct('abaccac', 'ac'))

Copy List with Random Pointer

這道題還是挺有意思的,咋一看題不知道考點在哪裡?看了挺久才理解原來是random指標和深拷貝。所謂為深拷貝是需要重新申請一塊記憶體,使其結構與原連結串列完全相同。也就是說對應連結串列中的節點的label值要對應相同,並且random指標指向的物件也要對應到新的物件。

由於需要將原連結串列中的物件對應到新生成的物件,所以用一個dict來map原來的物件到新的物件。於是進行兩遍遍歷,第一遍生成新的連結串列,並且對新連結串列中的label值和next指標進行賦值,next指標直接指向新生成的下一個物件;第二遍遍歷,實現新連結串列中random指標的賦值。

注意讀懂題目,找到問題的trick所在。這道題我是用python寫的,可以使用物件名,如果使用C++寫的話,物件的標識就是物件的指標了,寫法上應該差不多。奉上python程式碼:

# Definition for singly-linked list with a random pointer.
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None

class Solution:
    # @param head, a RandomListNode
    # @return a RandomListNode
    def copyRandomList(self, head):
        if head == None:
            return None
            
        myMap = {}
        nHead = RandomListNode(head.label)
        myMap[head] = nHead
        p = head
        q = nHead
        while p != None:
            q.random = p.random
            if p.next != None:
                q.next = RandomListNode(p.next.label)
                myMap[p.next] = q.next
            else:
                q.next = None
            p = p.next
            q = q.next
        
        p = nHead
        while p!= None:
            if p.random != None:
                p.random = myMap[p.random]
            p = p.next
        return nHead
        

Binary Tree Maximum Path Sum

在一棵二叉樹中找到任意的一條路徑,使得該條路徑上的所有節點的值之和最大,該路徑可以起始於樹中任意節點,終止於樹中的任意節點。

初一看顯然有點像一個序列的最大連續子段和,這道題其實也有點類似。

我們知道,任意一個合法的路徑,必然是通過某個節點,我們稱之為root,從左子樹的某個節點開始,通過該root走到右子樹的某個節點終止達到最大的路徑和。那麼我們只需要記錄從子樹某個點開始連續走到當前節點的最大的和就行了,顯然如果是走到該節點之前的最大值小於0,那麼前面那一段的值就拋棄(丟棄前面一段小於0的路徑肯定更優,這個和最大子段和的思路是一樣的)。於是我們可以得到通過該節點的最大的子段和為root.val+leftMax+rightMax,然後用該值更新全域性最優解就可以了。

奉上程式碼吧,比較簡單。

# Definition for a  binary tree node
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    #def __init__(self):
    #    self.ans = 0
    # @param root, a tree node
    # @return an integer
    def maxPathSum(self, root):
        self.ans = -0xFFFFFFF
        self.dfs(root)
        return self.ans
        
    def dfs(self, root):
        if root == None:
            return 0
        if root.left == None and root.right == None:
            self.ans = max(self.ans, root.val)
            return root.val
        
        leftMax = rightMax = 0
        if root.left != None:
            leftMax = max(0, self.dfs(root.left))
        if root.right != None:
            rightMax = max(0, self.dfs(root.right))
        
        self.ans = max(self.ans, leftMax+rightMax+root.val)
        return root.val+max(leftMax, rightMax)