LeetCode笔记:Weekly Contest 309

Posted Espresso Macchiato

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode笔记:Weekly Contest 309相关的知识,希望对你有一定的参考价值。

0. 赛后总结

这次的比赛结果有点出乎我的意料,本来以为两道题做错肯定凉凉了,结果意外的居然还是在国内前150,世界范围也是前300,就有点惊讶。

不过看了一下其他大佬们的解答之后多少有点明白了,我这全是暴力破解的能不快吗?

还是要好好学学大佬们的解答啊……

1. 题目一

给出题目一的试题链接如下:

1. 解题思路

这一题我的思路就是遍历一下26个字符,看一下其中存在的字符之间间隔的字符个数,是否与distance相一致。

2. 代码实现

给出python代码实现如下:

class Solution:
    def checkDistances(self, s: str, distance: List[int]) -> bool:
        n = len(s)
        for idx in range(26):
            ch = chr(ord('a') + idx)
            i = s.find(ch)
            if i != -1:
                j = s.find(ch, i+1)
                if distance[idx] != j-i-1:
                    return False
        return True

提交代码评测得到:耗时87ms,占用内存13.9MB。

2. 题目二

给出题目二的试题链接如下:

1. 解题思路

这一题我的思路是一个比较暴力的动态规划算法,就没必要过多介绍了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def numberOfWays(self, startPos: int, endPos: int, k: int) -> int:
        MOD = 10**9+7
        
        @lru_cache(None)
        def dp(st, ed, k):
            if abs(ed-st) > k:
                return 0
            elif abs(ed-st) == k:
                return 1
            return (dp(st+1, ed, k-1) + dp(st-1, ed, k-1)) % MOD
        
        return dp(startPos, endPos, k)

提交代码评测得到:耗时2553ms,占用内存302.8MB。

3. 算法优化

这一题思路上来说其实有一个更加简单的思路,就是当成一个排列组合问题,首先要存在路线,那么奇偶性必须满足条件,然后起点和终点之间的绝对距离必须不大于k。

剩下的,我们就可以用一个排列组合问题来求解就行了,我们只需要计算出朝左走的步数 k ′ k' k,然后就是求出组合数 C k k ′ C_k^k' Ckk即可。

给出python代码实现如下:

class Solution:
    @lru_cache(None)
    def Cnm(self, n, k):
        MOD = 10**9 + 7
        if k == 0 or k == n:
            return 1
        return self.Cnm(n-1, k) * n * pow(n-k, -1, MOD) % MOD
    
    def numberOfWays(self, startPos: int, endPos: int, k: int) -> int:
        d = endPos - startPos
        if d % 2 != k % 2 or abs(d) > k:
            return 0
        r = (k - d) // 2
        l = k - r
        return self.Cnm(k, r)          

提交代码评测得到:耗时58ms,占用内存15.2MB。

3. 题目三

给出题目三的试题链接如下:

1. 解题思路

这一题我们的思路依然是使用滑动窗口,显然,要让位与操作之后所有位都为0,那么也就是说每一位上最多只能有一个数上有值。

因此,我们只要维护一个滑动窗口,确保每一位上至多一个一个数有值即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def longestNiceSubarray(self, nums: List[int]) -> int:
        digits = [0 for _ in range(32)]
        res = 0
        i, j, n = 0, 0, len(nums)
        while j < n:
            x = nums[j]
            k = 0
            while x != 0:
                digits[k] += x % 2
                x = x // 2
                k += 1
            j += 1
            while i < j and any(d > 1 for d in digits):
                x = nums[i]
                k = 0
                while x != 0:
                    digits[k] -= x % 2
                    x = x // 2
                    k += 1
                i += 1
            res = max(res, j-i)
        return res

提交代码评测得到:耗时5171ms,占用内存28.9MB。

3. 算法优化

这一题的算法优化事实上并没有思路上的优化,依然还是使用滑动窗口。

不过这里对于每一位的计数操作事实上是非常笨重的,我们可以使用位操作直接进行替换,从而大幅提升代码的计算效率。

给出python代码实现如下:

class Solution:
    def longestNiceSubarray(self, nums: List[int]) -> int:
        s = 0
        res = 0
        i, j, n = 0, 0, len(nums)
        while j < n:
            x = nums[j]
            j += 1
            while i < j and s & x != 0:
                s = s ^ nums[i]
                i += 1
            s = s | x
            res = max(res, j-i)
        return res

提交代码评测得到:耗时766ms,占用内存28.8MB。

4. 题目四

给出题目四的试题链接如下:

1. 解题思路

这一题的思路的思路就是对每一个会议开始的时候找到可用的会议室,然后分配之后计数即可。

因此,我们就需要记录下每一个会议室最近的可用时刻,然后看每一个会议开始的时候有哪些会议室可用,然后进行分配。

不过这里有两个需要注意的事:

  1. 每一个会议开始的时候可能有多个会议室可用,他们的最近可用时间可能更早,也就是存在一定的空置时间,因此需要对这部分会议室进行统一处理然后选择最小id的会议室进行分配;
  2. 会议并没有根据开始时间进行排序,因此,我们需要首先对会议按照开始时间进行排序;

2. 代码实现

给出python代码实现如下:

class Solution:
    def mostBooked(self, n: int, meetings: List[List[int]]) -> int:
        meetings = sorted([(st, i, ed) for i, (st, ed) in enumerate(meetings)])
        avail = [(0, i) for i in range(n)]
        cnt = [0 for _ in range(n)]
        for st, _, ed in meetings:
            t, idx = heapq.heappop(avail)
            while t < st:
                t = st
                heapq.heappush(avail, (t, idx))
                t, idx = heapq.heappop(avail)
            cnt[idx] += 1
            heapq.heappush(avail, (max(t, st) + ed-st, idx))
        _max = max(cnt)
        for i in range(n):
            if cnt[i] == _max:
                return i
        return -1

提交代码评测得到:耗时4237ms,占用内存60.4MB。

以上是关于LeetCode笔记:Weekly Contest 309的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode笔记:Weekly Contest 317

LeetCode笔记:Weekly Contest 288

LeetCode笔记:Weekly Contest 299

LeetCode笔记:Weekly Contest 307

LeetCode笔记:Weekly Contest 325

LeetCode笔记:Weekly Contest 314