LeetCode笔记:Weekly Contest 209 比赛记录

    科技2022-08-02  96

    LeetCode笔记:Weekly Contest 209 0. 赛后总结1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现

    0. 赛后总结

    这一次的比赛算是中规中矩吧,花了四十来分钟,完成了3题,最后一题没能搞定。成绩上来说倒是不算差,国内181名,世界538名。大概因为做出最后一题的人确实不多吧。

    总之,回头好好研究一下最后一题吧,总感觉思路还是有的,就差临门一脚的实现。

    1. 题目一

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

    5531. 特殊数组的特征值

    1. 解题思路

    这一题的本质就是遍历1~n,看是否有一个值i刚好满足有i个数大于它。因此,我们只首先需要对整个数组进行一次排序,而后依次搜索即可。

    2. 代码实现

    给出python代码实现如下:

    class Solution: def specialArray(self, nums: List[int]) -> int: nums = sorted(nums) n = len(nums) if n <= nums[0]: return n for i in range(n-1): _min = nums[i] _max = nums[i+1] if n-i-1 > _min and n-i-1 <= _max: return n-i-1 return -1

    提交代码后评测得到:耗时24ms,占用内存14.2MB。属于当前最优方案。

    2. 题目二

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

    5532. 奇偶树

    1. 解题思路

    这一题本质上来说就是一个二叉树的逐层遍历,唯一需要多做一步的就是对每一层按照奇偶性进行一次大小检查。因此就不需要多做展开了,应该都知道。

    2. 代码实现

    给出python代码实现如下:

    class Solution: def isEvenOddTree(self, root: TreeNode) -> bool: queue = [root] level = 0 while queue != []: new_queue = [] node = queue.pop(0) if node.val % 2 == level % 2: return False if node.left: new_queue.append(node.left) if node.right: new_queue.append(node.right) last_val = node.val while queue != []: node = queue.pop(0) if node.val % 2 == level % 2: return False if level % 2 == 0 and node.val <= last_val: return False elif level % 2 == 1 and node.val >= last_val: return False if node.left: new_queue.append(node.left) if node.right: new_queue.append(node.right) last_val = node.val queue = new_queue level += 1 return True

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

    当前最优代码实现耗时336ms,但是看了一下思路上是大差不差的,因此也就不再多做展开了,有兴趣的读者可以自己去看一下。

    3. 题目三

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

    5534. 可见点的最大数目

    1. 解题思路

    这一题的我的思路就是把每一个点的角度算出来,然后看一下以每个点为起点的逆时针 θ \theta θ角度里面有多少的点存在于其中。

    需要注意的点有以下几点:

    由于是一个圆,所以当小角度的 α α α可能会出现在接近360的视角起点的范围内,需要注意考察以下,不能遗漏也不要重复计算;当点和观察者位置重合时,无论何种角度都能直接看到,因此需要特殊处理一下,不能够当成某个特定的角度来看待;由于计算机是离散计算,需要注意精度问题,避免由于精度导致的角度计算不一致(事实上比赛的时候我就在这里挂了一次)。

    2. 代码实现

    给出python代码实现如下:

    import math class Solution: def visiblePoints(self, points: List[List[int]], angle: int, location: List[int]) -> int: delta = 1e-7 def cal_angle(x, y): x0, y0 = location xd, yd = x - x0, y-y0 if yd == 0: return 0 if xd >= 0 else 180 elif xd == 0: return 90 if yd >= 0 else 270 theta = 180 * math.acos(xd / math.sqrt(xd**2 + yd **2)) / math.pi return theta if yd > 0 else 360 - theta angle_list = [] always_seen = 0 for x, y in points: if location[0] == x and location[1] == y: always_seen += 1 else: angle_list.append(cal_angle(x, y)) angle_list = sorted(angle_list) n = len(points) angle_list += [x+360 for x in angle_list if x + 360 <= angle_list[-1] + angle] m = len(angle_list) j = 0 ans = 0 for i in range(n): while j < m and angle_list[j]-angle_list[i] <= angle + delta: j += 1 ans = max(ans, min(j - i, n)) return ans + always_seen

    提交代码之后评测得到:耗时1948ms,占用内存59.9MB。

    当前最优的方案耗时仅708ms,但是看了一下它的代码,和我们的思路是几乎完全一致的,然后重新提交了一下他们的代码,发现评测耗时1704ms,和我们的实现并没有太过显著的差异,因此这里就不再展开了。

    4. 题目四

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

    5533. 使整数变为 0 的最少操作次数

    1. 解题思路

    这一题比赛的时候没能搞定,赛后想了好一阵子,后来做到是做出来了,但是其实也是手写了一堆结果之后整理得到的结论。

    思路上大致来说肯定是递归没跑了,问题是递归公式怎么构建,我们整理得到:

    从0到构建第i位为1,其他位全部为0的数需要的总步数为 2 i − 1 2^{i}-1 2i1次,其间恰好会遍历一遍从1到 2 i 2^{i} 2i之间的所有数;对任意一个数字k,从0构建k和从k变回0的过程是可逆的,即两者需要的步数完全相同。

    因此,我们可以给出递归公式如下,对任意一个二进制数 x 1 x 2 . . . x n x_1x_2...x_n x1x2...xn

    如果 x 1 x_1 x1为0,那么需要的步数就是构建 x 2 . . . x n x_2...x_n x2...xn需要的步数;如果 x 1 x_1 x1为1,那么需要的步数就是构建 10...0 10...0 10...0的步数(即 2 n − 1 2^n-1 2n1)减去构建 x 2 . . . x n x_2...x_n x2...xn需要的步数。

    2. 代码实现

    我们给出python代码实现如下:

    class Solution: def minimumOneBitOperations(self, n: int) -> int: digits = [] while n != 0: digits.append(n & 1) n = n >> 1 n = len(digits) flag = 2 ones = [] for i in range(n): ones.append(flag-1) flag *= 2 def dp(idx): if idx < 0: return 0 if idx == 0: return digits[idx] if digits[idx] == 0: return dp(idx-1) else: return ones[idx] - dp(idx-1) return dp(n-1)

    提交代码评测得到:耗时28ms,占用内存14.1MB。为当前最优实现方案。

    Processed: 0.014, SQL: 8