【周赛】第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]

 

你可能感兴趣的:(LeetCode周赛)