LeetCode笔记:Weekly Contest 330

Posted Espresso Macchiato

tags:

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

1. 题目一

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

1. 解题思路

这一题看似复杂,其实很显然对于每一次操作,假设n在原集合当中,那么n%(n-1)=1,下一次操作一定可以将n-1加入到集合当中,因此经过至多n-1此操作,一定能够将除了1之外的所有比n小的元素全部加入到集合当中,因此答案一定是 n − 1 n-1 n1

这里只有一个例外,即n=1的情况,此时答案就是1。

2. 代码实现

给出python代码实现如下:

class Solution:
    def distinctIntegers(self, n: int) -> int:
        return n-1 if n != 1 else 1

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

2. 题目二

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

1. 解题思路

这道题目其实也简单,对于任何一个n边形,猴子全部的移动方式共有 2 n 2^n 2n种,而要他们任意一只都不会相遇,那么只有两种情况,即要么全部往左跳,要么全部往右跳。故而答案显而易见就是 2 n − 2 2^n-2 2n2

剩下的就是如何求解这个答案了,由于 n n n可以非常大,因此我们采用二分求解就行了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def monkeyMove(self, n: int) -> int:
        MOD = 10**9 + 7
        
        @lru_cache(None)
        def factor(n):
            if n <= 1:
                return 2**n
            return factor(n//2) * factor((n+1) // 2) % MOD
        
        return (factor(n)-2 + MOD) % MOD

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

3. 题目三

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

1. 解题思路

这一题虽然这次划分难度划为了hard的题目,但是其实还是比较简单的。

因为这里的分装方式,其实就是在序列当中找 k − 1 k-1 k1个位置进行切分,然后产生的cost就是这 k − 1 k-1 k1个间隔位置左右元素之和。

因此,我们只需要考察全部的 k − 1 k-1 k1个间隔各自会带来的cost,然后进行排序,取最大的 k − 1 k-1 k1个元素之和减去最小的 k − 1 k-1 k1元素之和就是我们最终的答案。

2. 代码实现

给出python代码实现如下:

class Solution:
    def putMarbles(self, weights: List[int], k: int) -> int:
        if k == 1:
            return 0
        n = len(weights)
        intervals = [weights[i] + weights[i+1] for i in range(n-1)]
        intervals = sorted(intervals)
        return sum(intervals[-(k-1):]) - sum(intervals[:k-1])

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

4. 题目四

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

1. 解题思路

这道题坦率地说我没啥很好的思路,最后算是暴力求解的,万幸勉强可以通过测试样例,就还好……

我的思路非常暴力,就是首先定位中间就,k位置上的两个元素u,v,如果他们满足逆序条件,那么就找出第j个元素左侧小于v的元素个数以及第k个元素右侧大于u的元素个数,两者相乘就是这一组中间元素对应的4元组的数目。

遍历所有的j,k即可获得最终的答案,整体的时间复杂度就是 O ( N 2 ) O(N^2) O(N2),其实还是非常高的……

2. 代码实现

给出python代码实现如下:

class Solution:
    def countQuadruplets(self, nums: List[int]) -> int:
        n = len(nums)
        nums = [x-1 for x in nums]
        
        left_small = [[0 for _ in range(n)] for _ in range(n)]
        for i in range(n-1):
            for j in range(nums[i]):
                left_small[i+1][j] = left_small[i][j]
            for j in range(nums[i]+1, n):
                left_small[i+1][j] = left_small[i][j] + 1
        
        right_big = [[0 for _ in range(n)] for _ in range(n)]
        for i in range(n-2, -1, -1):
            for j in range(nums[i+1]):
                right_big[i][j] = right_big[i+1][j] + 1
            for j in range(nums[i+1], n):
                right_big[i][j] = right_big[i+1][j]
        
        res = 0
        for i in range(1, n-2):
            for j in range(i+1, n-1):
                if nums[i] < nums[j]:
                    continue
                res += left_small[i][nums[j]] * right_big[j][nums[i]]
        return res

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

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

LeetCode笔记:Weekly Contest 317

LeetCode笔记:Weekly Contest 288

LeetCode笔记:Weekly Contest 299

LeetCode笔记:Weekly Contest 307

LeetCode笔记:Weekly Contest 325

LeetCode笔记:Weekly Contest 314