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
n−1。
这里只有一个例外,即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 2n−2。
剩下的就是如何求解这个答案了,由于 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 k−1个位置进行切分,然后产生的cost就是这 k − 1 k-1 k−1个间隔位置左右元素之和。
因此,我们只需要考察全部的 k − 1 k-1 k−1个间隔各自会带来的cost,然后进行排序,取最大的 k − 1 k-1 k−1个元素之和减去最小的 k − 1 k-1 k−1元素之和就是我们最终的答案。
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的主要内容,如果未能解决你的问题,请参考以下文章