LeetCode Contest 209
这次只能做出前面三题,而且第三题用时过长,导致这次排名只有505。
第一题Special Array With X Elements Greater Than or Equal X
暴力枚举所有可能的 x
。
class Solution:
def specialArray(self, nums: List[int]) -> int:
for n in range(len(nums) + 1):
if sum(1 for v in nums if v >= n) == n:
return n
return -1
第二题Even Odd Tree
BFS找出每一层来判断是否满足条件。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isEvenOddTree(self, root: TreeNode) -> bool:
level = 0
cur = [root]
while cur:
next = []
nums = []
for node in cur:
if node is None:
continue
nums.append(node.val)
next.append(node.left)
next.append(node.right)
if level % 2 == 1:
if any(a % 2 == 1 for a in nums) or any(a <= b for a, b in zip(nums, nums[1:])):
return False
else:
if any(a % 2 == 0 for a in nums) or any(a >= b for a, b in zip(nums, nums[1:])):
return False
cur = next
level += 1
return True
第三题Maximum Number of Visible Points
首先根据圆心算出所有点的角度(x轴正方向为 0 度),然后按照大小排序。然后用 two pointers 来找出角度差为 angle
的最大长度。需要注意的是如果两个角度的差大于 180 度,那么我们要将这个角度差调整成 360 - 角度差。为了方便,我将所有的角度每个加上 360 也考虑进来,这样就不用调整了。
class Solution:
def visiblePoints(self, points: List[List[int]], angle: int, location: List[int]) -> int:
x, y = location
base = 0
degrees = []
for a, b in points:
if a == x and b == y:
base += 1
continue
degrees.append(math.degrees(math.atan2(b - y, a - x)))
degrees.append(degrees[-1] + 360)
degrees.sort()
ans = i = j = 0
while i < len(degrees):
while i < len(degrees) and degrees[i] - degrees[j] <= angle:
i += 1
ans = max(ans, i - j)
j += 1
return ans + base
第四题Minimum One Bit Operations to Make Integers Zero
一开始的时候假设 n 的二进制是 1x...x,长度为 l。为了将最高位的 1 变成 0,我们必须要将 1x...x 变成 110...0。而110...0 变成0的操作次数是 2l,所以我们只需要求出将 x...x 变成 10...0 的最小步数。x...x 的长度为 l - 1,但是我们希望将其变成 10..0,而不是 0。总结以下,我们将原来的问题转化成:给定一个长度是 l 的 01 序列 x...x, 将其变成 c0...0 至少需要 f(x...x, c0...0) 步,求 f(x...x, c0...0)。c 是 0 或 1。这个想法让我有了以下的算法:
为了方便讨论,我们将 01 序列的最左那位用 y 表示。假设当前 01 序列是 yx...x, 长度为l,我们需要将其变成 c0...0。
(1)如果 y = c,那么
(2)如果 y != c,那么有两种情况 (y, c) = (1, 0) 或者 (0, 1)。
(2.1)(y, c) = (1, 0)。这种情况在前面已经讨论过,
(2.2)(y, c) = (0, 1)。这种情况下,0x...x -> 10...0 的最优方案是
0x...x -> 010...0 -> 10...0
不难看出,010...0 -> 10...0 需要 2l 步,所以
因此,在 y != c 的情况下
比赛的时候 (2.2) 的分析一直没有弄对,有点可惜了。
class Solution:
def minimumOneBitOperations(self, n: int) -> int:
bit = []
while n:
bit.append(n & 1)
n //= 2
ans = c = 0
for i in range(len(bit) - 1, -1, -1):
if c != bit[i]:
ans += 2 ** i
c = 1
else:
c = 0
return ans