[Leetcode Weekly Contest]182

链接:LeetCode

[Leetcode]1394. 找出数组中的幸运数

在整数数组中,如果一个整数的出现频次和它的数值大小相等,我们就称这个整数为「幸运数」。
给你一个整数数组 arr,请你从中找出并返回一个幸运数。

  • 如果数组中存在多个幸运数,只需返回 最大 的那个。
  • 如果数组中不含幸运数,则返回 -1 。

字典不解释。

import collections
class Solution:
    def findLucky(self, arr: List[int]) -> int:
        count = collections.Counter(arr)
        res = -1
        for key in set(arr):
            if key == count[key]:
                res = max(res,key)
        return res

[Leetcode]1395. 统计作战单位数

每 3 个士兵可以组成一个作战单位,分组规则如下:
从队伍中选出下标分别为 i、j、k 的 3 名士兵,他们的评分分别为 \(rating[i]\)\(rating[j]\)\(rating[k]\)
作战单位需满足:\(rating[i] < rating[j] < rating[k]\)或者\(rating[i] > rating[j] > rating[k]\),其中$ 0 <= i < j < k < n$
请你返回按上述条件可以组建的作战单位数量。每个士兵都可以是多个作战单位的一部分。

一个通用的想法是,是以某个位置作为固定数,比较两侧满足升序或者降序的士兵的个数,相乘相加即可。在寻找两侧比其大/小的数,可以采用遍历或者线段树的方法。

class Solution:
    def numTeams(self, rating: List[int]) -> int:
        return self.getNum(rating)+self.getNum(rating[::-1])

    # 左小右大
    def getNum(self,nums):
        left = [0 for i in range(len(nums))]
        right = [0 for i in range(len(nums))]
        for i in range(len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    left[i] += 1
            for j in range(i+1,len(nums)):
                if nums[j] > nums[i]:
                    right[i] += 1
        res = 0
        for i in range(len(nums)):
            res += left[i] * right[i]
        return res

[Leetcode]1396. 设计地铁系统

请你实现一个类 UndergroundSystem ,它支持以下 3 种方法:
1. checkIn(int id, string stationName, int t)
编号为 id 的乘客在 t 时刻进入地铁站 stationName 。
一个乘客在同一时间只能在一个地铁站进入或者离开。
2. checkOut(int id, string stationName, int t)
编号为 id 的乘客在 t 时刻离开地铁站 stationName 。
3. getAverageTime(string startStation, string endStation)

  • 返回从地铁站 startStation 到地铁站 endStation 的平均花费时间。
  • 平均时间计算的行程包括当前为止所有从 startStation 直接到达 endStation 的行程。
  • 调用 getAverageTime 时,询问的路线至少包含一趟行程。

你可以假设所有对 checkIn 和 checkOut 的调用都是符合逻辑的。也就是说,如果一个顾客在 t1 时刻到达某个地铁站,那么他离开的时间 t2 一定满足 t2 > t1 。所有的事件都按时间顺序给出。

使用字典保存信息,在查询平均时间时,只需要查询两个车站,得到总时间,和总次数

class UndergroundSystem:
    def __init__(self):
        self.ids = {}
        self.underground = {}

    def checkIn(self, id: int, stationName: str, t: int) -> None:
        self.ids[id] = [stationName,t]

    def checkOut(self, id: int, stationName: str, t: int) -> None:
        start_stationName,start_time = self.ids[id]
        check_stationName = start_stationName+stationName
        pay_time = t-start_time
        if check_stationName not in self.underground:
            self.underground[check_stationName] = [1,pay_time]
        else:
            self.underground[check_stationName][0] += 1
            self.underground[check_stationName][1] += pay_time


    def getAverageTime(self, startStation: str, endStation: str) -> float:
        times,time = self.underground[startStation+endStation]
        return time/times



# Your UndergroundSystem object will be instantiated and called as such:
# obj = UndergroundSystem()
# obj.checkIn(id,stationName,t)
# obj.checkOut(id,stationName,t)
# param_3 = obj.getAverageTime(startStation,endStation)

[Leetcode]1397. 找到所有好字符串

给你两个长度为 n 的字符串 s1 和 s2 ,以及一个字符串 evil 。请你返回 好字符串 的数目。
好字符串 的定义为:它的长度为 n ,字典序大于等于 s1 ,字典序小于等于 s2 ,且不包含 evil 为子字符串。
由于答案可能很大,请你返回答案对\(10^9 + 7\)取余的结果。
示例 1:
输入:n = 2, s1 = "aa", s2 = "da", evil = "b"
输出:51
解释:总共有 25 个以 'a' 开头的好字符串:"aa","ac","ad",...,"az"。还有 25 个以 'c' 开头的好字符串:"ca","cc","cd",...,"cz"。最后,还有一个以 'd' 开头的好字符串:"da"。
示例 2:
输入:n = 8, s1 = "leetcode", s2 = "leetgoes", evil = "leet"
输出:0
解释:所有字典序大于等于 s1 且小于等于 s2 的字符串都以 evil 字符串 "leet" 开头。所以没有好字符串。
示例 3:
输入:n = 2, s1 = "gx", s2 = "gz", evil = "x"
输出:2

这道题是本周的压轴题,也是我第一次接触这种题型,收获很大,采用的是数位 DP + KMP的方法。数位DP 问题往往都是这样的题型,给定一个闭区间\([l, r]\),让你求这个区间中满足某种条件的数的总数。数位DP实际上是DFS+记忆化搜索,关于数位DP的基础知识可以参考数位DP
这道题的最大难点在于,我们要求计算有多少个字符串“不包含”某个子串,通过KMP算法是便于我们找出当前字符串与模式串的最大匹配位数,当出现下一位不匹配时,我们可以直接找出下一个需要匹配的字符位置,这里也就是next数组的作用了。

class Solution:
    def findGoodStrings(self, n: int, s1: str, s2: str, evil: str) -> int:
        MOD = 1000000007
        if s1 > s2:
            return 0
        self.next_ = self.getNext(evil)
        self.dp = [[-1 for j in range(len(evil))] for i in range(n)]
        ans = self.dfs(s2,evil,0, 0, True) % MOD - self.dfs(s1,evil,0, 0, True) % MOD + MOD
        if evil not in s1:
            ans += 1
        return ans % MOD

    def getNext(self, p):
        p += '*'
        len_p = len(p)
        next = [-1 for i in range(len_p)]
        j,k = 0,-1
        while j<len_p-1:
            if p[j] == p[k] or k==-1:
                j+=1
                k+=1
                next[j] = k
            else:
                k = next[k]
        return next

    def dfs(self,s,evil,x,match,flag):
        n,m = len(s),len(evil)
        if match >= m:
            return 0
        if x >= n:
            return 1
        if not flag and  self.dp[x][match] != -1:
            return self.dp[x][match];
        lim = s[x] if flag else 'z'
        ret = 0
        for k in range(ord('a'),ord(lim)+1):
            cur = chr(k)
            nxt = match;
            while nxt > 0 and evil[nxt] != cur:
                  nxt = self.next_[nxt]
            if cur == evil[nxt]: nxt += 1
            ret += self.dfs(s,evil,x + 1, nxt, flag and (cur == lim))

        if not flag: self.dp[x][match] = ret
        return ret

参考:
leetcode

posted @ 2020-04-02 13:14  Jamest  阅读(237)  评论(0编辑  收藏  举报