[Leetcode Weekly Contest]178

链接:LeetCode

[Leetcode]1365.有多少小于当前数字的数字

给你一个数组nums,对于其中每个元素 \(nums[i]\),请你统计数组中比它小的所有数字的数目。
换而言之,对于每个\(nums[i]\)你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 \(nums[j] < nums[i]\)
以数组形式返回答案。

示例 1:
输入:\(nums = [8,1,2,2,3]\)
输出:\([4,0,1,1,3]\)
解释:
对于 \(nums[0]=8\)存在四个比它小的数字:(1,2,2 和 3)。
对于 \(nums[1]=1\)不存在比它小的数字。
对于 \(nums[2]=2\)存在一个比它小的数字:(1)。
对于 \(nums[3]=2\)存在一个比它小的数字:(1)。
对于 \(nums[4]=3\)存在三个比它小的数字:(1,2 和 2)。

这周周赛的前两天也是很常规的排序题,对于这种类型的题搞清逻辑即可。

class Solution:
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        if not nums:
            return []
        n = len(nums)
        enum = list(enumerate(nums))
        enum.sort(key=lambda x:x[1])
        res = [0 for i in range(n)]
        last_ind,last_num = enum[0]
        for i in range(1,len(enum)):
            ind,num = enum[i]
            if num >  last_num:
                res[ind] = i
            else:
                res[ind] =  res[last_ind]
            last_ind,last_num = ind,num
        return res

[Leetcode]1366. 通过投票对团队排名

现在有一个特殊的排名系统,依据参赛团队在投票人心中的次序进行排名,每个投票者都需要按从高到低的顺序对参与排名的所有团队进行排位。
排名规则如下:
参赛团队的排名次序依照其所获「排位第一」的票的多少决定。如果存在多个团队并列的情况,将继续考虑其「排位第二」的票的数量。以此类推,直到不再存在并列的情况。
如果在考虑完所有投票情况后仍然出现并列现象,则根据团队字母的字母顺序进行排名。
给你一个字符串数组 votes 代表全体投票者给出的排位情况,请你根据上述排名规则对所有参赛团队进行排名。
请你返回能表示按排名系统 排序后 的所有团队排名的字符串。

示例 1:
输入:\(votes = ["ABC","ACB","ABC","ACB","ACB"]\)
输出:"ACB"
解释:A 队获得五票「排位第一」,没有其他队获得「排位第一」,所以 A 队排名第一。
B 队获得两票「排位第二」,三票「排位第三」。
C 队获得三票「排位第二」,两票「排位第三」。
由于 C 队「排位第二」的票数较多,所以 C 队排第二,B 队排第三。

搞清规则后,构建一个list,依次加入排序需要比较的数量即可。

class Solution:
    def rankTeams(self, votes: List[str]) -> str:
        rank_num = len(votes[0])
        rank_dic = {j:i for i,j in enumerate(votes[0])}
        rank = [[0 for j in range(rank_num+1)]for i in range(rank_num)]
        for vote in votes:
            for ind,j in enumerate(vote):
                rank[rank_dic[j]][ind] -= 1
        for i in range(rank_num):
            rank[i][-1] = votes[0][i]
        rank.sort()
        return ''.join([x[-1] for x in rank])

[Leetcode]1367. 二叉树中的列表

给一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。
如果在二叉树中,存在一条一直向下的路径,且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 True ,否则返回 False 。一直向下的路径的意思是:从树中某个节点开始,一直连续向下的路径。

这道题类似于剑指offer面试题26.树的子结构。在判断时注意使用两层递归,外层递归解决链表的头和tree的某个node匹配的问题,内层递归解决链表的某个node和tree的某个node匹配的问题。

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

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

class Solution:
    def isSubPath(self, head: ListNode, root: TreeNode) -> bool:
        if not root:
            return False
        return self.dfs(head,root) or self.isSubPath(head,root.left) or self.isSubPath(head,root.right)
    
    def dfs(self,head,root):
        if not head:
            return True
        if not root:
            return False
        return head.val == root.val and (self.dfs(head.next,root.left) or self.dfs(head.next,root.right))

[Leetcode]1368. 使网格图至少有一条有效路径的最小代价

给你一个 m x n 的网格图 grid 。 grid 中每个格子都有一个数字,对应着从该格子出发下一步走的方向。\(grid[i][j]\)中的数字可能为以下几种情况:
1 ,下一步往右走,也就是你会从\(grid[i][j]\)走到\(grid[i][j + 1]\)
2 ,下一步往左走,也就是你会从\(grid[i][j]\)走到\(grid[i][j - 1]\)
3 ,下一步往下走,也就是你会从\(grid[i][j]\)走到\(grid[i + 1][j]\)
4 ,下一步往上走,也就是你会从\(grid[i][j]\)走到\(grid[i - 1][j]\)
注意网格图中可能会有 无效数字 ,因为它们可能指向 grid 以外的区域。
一开始,你会从最左上角的格子 (0,0) 出发。我们定义一条 有效路径 为从格子 (0,0) 出发,每一步都顺着数字对应方向走,最终在最右下角的格子 (m - 1, n - 1) 结束的路径。有效路径 不需要是最短路径 。
你可以花费 cost = 1 的代价修改一个格子中的数字,但每个格子中的数字 只能修改一次 。
示例 1:
示例 1
输入:grid =\([[1,1,1,1],[2,2,2,2],[1,1,1,1],[2,2,2,2]]\)
输出:3
解释:你将从点 (0, 0) 出发。
到达 (3, 3) 的路径为: (0, 0) --> (0, 1) --> (0, 2) --> (0, 3) 花费代价 cost = 1 使方向向下 --> (1, 3) --> (1, 2) --> (1, 1) --> (1, 0) 花费代价 cost = 1 使方向向下 --> (2, 0) --> (2, 1) --> (2, 2) --> (2, 3) 花费代价 cost = 1 使方向向下 --> (3, 3)
总花费为 cost = 3.

比较容易理解的一种解法是BFS。通过广度优先搜索更新cost。另外一种更优化的办法是采用0-1BFS,如果前进到下一个位置不需要代价,则插入到队首。如果前进到下一个位置需要代价,那么插入到队尾。这样就能保证整个队列是有序的。用一个最短路径数组维护位置的最短路径。

import heapq
class Solution:
    def minCost(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        q = []
        vis = [[False] * n for _ in range(m)]
        dis = [[float('inf')] * n for _ in range(m)] # INF
        di = [(0, 1), (0, -1), (1, 0), [-1, 0]]
        heapq.heappush(q, (0, (0, 0)))
        while q:
            cost, (i, j) = heapq.heappop(q)
            if i == m - 1 and j == n - 1:
                return cost
            vis[i][j] = True

            for idx in range(4):
                next_i, next_j = i + di[idx][0], j + di[idx][1]
                if next_i >= 0 and next_i < m and next_j >= 0 and next_j < n:
                    if vis[next_i][next_j]: continue
                    new_cost = cost if grid[i][j] == idx + 1 else cost + 1
                    if new_cost < dis[next_i][next_j]:
                        dis[next_i][next_j] = new_cost
                        heapq.heappush(q, (new_cost, (next_i, next_j)))
    def minCost_01(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        q = [(0, (0, 0))]
        vis = [[False] * n for _ in range(m)]
        dis = [[float('inf')] * n for _ in range(m)] 
        di = [(0, 1), (0, -1), (1, 0), [-1, 0]]
        while q:
            cost, (i, j) = heapq.heappop(q)
            if i == m - 1 and j == n - 1:
                return cost
            vis[i][j] = True

            for idx in range(4):
                next_i, next_j = i + di[idx][0], j + di[idx][1]
                if next_i >= 0 and next_i < m and next_j >= 0 and next_j < n:
                    if vis[next_i][next_j]: continue
                    new_cost = cost if grid[i][j] == idx + 1 else cost + 1
                    if new_cost < dis[next_i][next_j]:
                        dis[next_i][next_j] = new_cost
                        if new_cost == cost:q.insert(0,(new_cost, (next_i, next_j)))
                        else:q.append((new_cost, (next_i, next_j)))
posted @ 2020-03-02 16:18  Jamest  阅读(287)  评论(0编辑  收藏  举报