【周賽】第164場-2019-11-24

目錄

1-Minimum Time Visiting All Points-easy。array

2-Count Servers that Communicate-medium。array

3-Search Suggestions System-medium。trie

4-Number of Ways to Stay in the Same Place After Some Steps-hard。DP


1-Minimum Time Visiting All Points-easy。array

On a plane there are n points with integer coordinates points[i] = [xi, yi]. Your task is to find the minimum time in seconds to visit all points.

You can move according to the next rules:

  • In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second).
  • You have to visit the points in the same order as they appear in the array.
Input: points = [[1,1],[3,4],[-1,0]]
Output: 7
Explanation: One optimal path is [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0]   
Time from [1,1] to [3,4] = 3 seconds 
Time from [3,4] to [-1,0] = 4 seconds
Total time = 7 seconds

通過測試用例即可知計算相對最短路徑即可,等於兩者之間最大座標差

class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        if not points:
            return 0
        res = 0
        for i in range(1, len(points)):
            cur = max(abs(points[i][0] - points[i-1][0]), abs(points[i][1] - points[i-1][1]))
            res += cur
        return res

2-Count Servers that Communicate-medium。array

You are given a map of a server center, represented as a m * n integer matrix grid, where 1 means that on that cell there is a server and 0 means that it is no server. Two servers are said to communicate if they are on the same row or on the same column. Return the number of servers that communicate with any other server.

Input: grid = [[1,1,0,0],[0,0,1,0],[0,0,1,0],[0,0,0,1]]
Output: 4
Explanation: The two servers in the first row can communicate with each other. The two servers in the third column can communicate with each other. The server at right bottom corner can't communicate with any other server.

反向思考,先計算總共的server數量,再遍歷一遍把無com的結果去掉,剩下就是有com的結果 

from collections import deque
class Solution:
    def countServers(self, grid: List[List[int]]) -> int:
        if not grid:
            return 0
        m = len(grid)
        n = len(grid[0])
        res = 0
        row = [0]*m
        col = [0]*n
        for i in range(m):
            for j in range(n):
                if grid[i][j]:
                    res += 1
                    row[i] += 1
                    col[j] += 1           
        for i in range(m):
            for j in range(n):
                if grid[i][j] and row[i] <= 1 and col[j] <= 1:
                    res -= 1
        return res

3-Search Suggestions System-medium。trie

Given an array of strings products and a string searchWord. We want to design a system that suggests at most three product names from products after each character of searchWord is typed. Suggested products should have common prefix with the searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products.

Return list of lists of the suggested products after each character of searchWord is typed. 

Input: products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"
Output: [["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]

這道題在排名靠前的解法裏沒找到Trie的解法,只有暴力匹配加一點剪枝的trick

class Solution:
    def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
        products.sort()
        ans = []
        for i in range(len(searchWord)):
            temp = []
            j = 0
            while j < len(products):
                if searchWord[:i+1] == products[j][:i+1]:
                    if len(temp) < 3:
                        temp.append(products[j])
                    j += 1
                else:
                    products.pop(j) # 剪枝,把後續query不可能索引的結果先pop掉
            ans.append(temp)
        return ans

# 自己的做法,我覺得更reasonable,但有bug,27/41
class Solution:
    def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
        if not searchWord:
            return []
        trie = Trie()
        for pro in products:
            trie.add(pro)
        res = []
        for i in range(1, len(searchWord)+1):
            cur = searchWord[:i]
            ans = trie.search(cur)
            res.append(ans)
        return res
    
class Trie:
    def __init__(self):
        self.root = {}
        self.end = True
    
    def add(self, w):
        add = self.root
        for c in w:
            add[c] = add.get(c, {})
            add = add[c]
        add[self.end] = True
    
    def search(self, w):
        search = self.root
        for c in w:
            if c not in search:
                return []
            search = search[c]
        res = []
        self.dfs(search, res, w)
        return res
        
    def dfs(self, dic, res, path):
        if not dic or self.end in dic:
            res.append(path)
        if len(res) >= 3:
            return
        for c in 'abcdefghijklmnopqrstuvwxyz':
            if c not in dic:
                continue
            if len(res) >= 3:
                break
            self.dfs(dic[c], res, path + c)
        return res

4-Number of Ways to Stay in the Same Place After Some Steps-hard。DP

You have a pointer at index 0 in an array of size arrLen. At each step, you can move 1 position to the left, 1 position to the right in the array or stay in the same place  (The pointer should not be placed outside the array at any time).

Given two integers steps and arrLen, return the number of ways such that your pointer still at index 0 after exactly steps steps.

Since the answer may be too large, return it modulo 10^9 + 7.

Constraints:

  • 1 <= steps <= 500
  • 1 <= arrLen <= 10^6
Input: steps = 2, arrLen = 4
Output: 2
Explanation: There are 2 differents ways to stay at index 0 after 2 steps
Right, Left
Stay, Stay

這道題keys是2個

  • 涉及到steps和arrLen,所以是個二元DP問題,想清楚dp[i][j]的含義,這裏是耗步數i步停留在下標爲j的可能性數量
  • 轉換方程。dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j+1],表示再i-1的基礎上,再走一步到j位置,對應stay + right + left。這裏一開始錯誤理解了題意,以爲可以向左向右跳任意步長,實際只能跳1步
  • 邊界條件,初始化爲0,默認dp[i][j] = 1
  • critical trick,這裏arrLen如果比steps更長,更長的部分是沒有意義的,因爲最遠也跳不到超過steps的位置,所以這裏可以剪枝,把更長的部分減掉(否則後續會TLE,看constraints就知道)
class Solution:
    def numWays(self, steps: int, arrLen: int) -> int:
        if arrLen > steps: # important trick
            arrLen = steps
        MOD = 10**9 + 7
        dp = [[0 for _ in range(arrLen+1)] for _ in range(steps+1)]
        dp[0][0] = 1
        for i in range(1, steps+1):
            for j in range(arrLen+1):
                dp[i][j] += dp[i-1][j]
                for k in [-1, 1]:
                    if j+k >= 0 and j+k < arrLen:
                        dp[i][j] += dp[i-1][j+k]
                dp[i][j] %= MOD
        return dp[steps][0]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章