计算列车到站时间
这道题目比较简单,只需要将正点到站时间和延误时间相加,然后对24取模,就可以得到实际到站时间。注意,如果结果是0,表示到站时间是00:00。
代码如下:
class Solution:
def findDelayedArrivalTime(self, arrivalTime: int, delayedTime: int) -> int:
# 将正点到站时间和延误时间相加,对24取模
return (arrivalTime + delayedTime) % 24
时间复杂度:O(1) 空间复杂度:O(1)
倍数求和
这道题目可以利用容斥原理和等差数列求和公式来优化。容斥原理是一种计算集合并的方法,它可以避免重复计算或漏算。等差数列求和公式是一种快速计算等差数列前n项和的方法,它只需要知道首项、末项和项数。
具体来说,我们可以先计算[1,n]范围内能被3、5、7整除的数的和,然后减去能被15、21、35整除的数的和(因为这些数同时被两个因子整除了),最后加上能被105整除的数的和(因为这些数同时被三个因子整除了)。这样就可以避免重复或漏算。
代码如下:
class Solution:
def sumOfMultiples(self, n: int) -> int:
# 定义一个辅助函数,计算能被k整除的数的和
def sum(n, k):
# 等差数列求和公式:(首项 + 末项) * 项数 / 2
return (k + (n // k * k)) * (n // k) // 2
# 利用容斥原理计算结果
return sum(n, 3) + sum(n, 5) + sum(n, 7) - sum(n, 15) - sum(n, 21) - sum(n, 35) + sum(n, 105)
时间复杂度:O(1) 空间复杂度:O(1)
滑动子数组的美丽值
这道题目可以用滑动窗口的思想来解决。我们维护一个长度为k的窗口,每次移动一位,并更新窗口内元素的最小值、最大值和美丽值。美丽值定义为最大值减去最小值。
为了快速找到窗口内元素的最小值和最大值,我们可以使用两个数据结构:一个是有序集合(如TreeSet),它可以在O(logk)的时间内插入、删除和查找元素;另一个是双端队列(如Deque),它可以在O(1)的时间内维护窗口内元素的单调性。
代码如下:
import collections
import bisect
class Solution:
def slidingBeautyValue(self, nums: List[int], k: int) -> int:
# 初始化有序集合和双端队列
sorted_set = []
min_queue = collections.deque()
max_queue = collections.deque()
# 定义一个辅助函数,计算窗口内元素的美丽值
def beauty():
return sorted_set[-1] - sorted_set[0]
# 初始化结果为0
ans = 0
# 遍历数组
for i in range(len(nums)):
# 如果窗口已满,移除左边界元素
if i >= k:
sorted_set.pop(bisect.bisect_left(sorted_set, nums[i - k]))
if min_queue[0] == nums[i - k]:
min_queue.popleft()
if max_queue[0] == nums[i - k]:
max_queue.popleft()
# 插入右边界元素到有序集合中
bisect.insort(sorted_set, nums[i])
# 维护最小值队列
while min_queue and min_queue[-1] > nums[i]:
min_queue.pop()
min_queue.append(nums[i])
# 维护最大值队列
while max_queue and max_queue[-1] < nums[i]:
max_queue.pop()
max_queue.append(nums[i])
# 如果窗口已满,更新结果
if i >= k - 1:
ans += beauty()
# 返回结果
return ans
时间复杂度:O(nlogk) 空间复杂度:O(k)
使数组所有元素变成1的最少操作次数
这道题目可以转化为寻找数组中GCD(最大公约数)为1的最短子数组。我们可以用前缀和+哈希表来快速求出任意区间内元素的GCD,并用双指针来维护一个滑动窗口。
具体来说,我们先遍历一遍数组,计算每个位置之前所有元素的GCD,并存储在哈希表中。然后我们用两个指针left和right表示窗口的左右边界,并维护一个变量cur表示当前窗口内元素的GCD。每次我们右移right指针,并更新cur为cur和nums[right]的GCD。如果cur为1,说明当前窗口满足条件,我们就尝试缩小窗口,即左移left指针,并更新cur为left之前所有元素的GCD与nums[left]之后所有元素的GCD之间的GCD。如果cur仍然为1,说明缩小后仍然满足条件,我们就更新结果为当前窗口长度;否则说明缩小后不满足条件,我们就恢复原来的窗口,并继续右移right指针。
代码如下:
import math
class Solution:
def minOperationsToOne(self, nums: List[int]) -> int:
# 定义一个辅助函数,计算两个数的GCD
def gcd(a, b):
return math.gcd(a, b)
# 初始化哈希表存储前缀GCD
prefix_gcd = {0:0}
# 遍历数组计算前缀GCD
for i in range(len(nums)):
prefix_gcd[i + 1] = gcd(prefix_gcd[i], nums[i])
# 如果整个数组的GCD不为1,直接返回-1
if prefix_gcd[len(nums)] != 1:
return -1
# 初始化左右指针、当前GCD、结果
left = 0
right = 0
cur = nums[0]
ans = len(nums)
# 遍历数组
while right < len(nums):
# 如果当前GCD为1,尝试缩小窗口
if cur == 1:
ans = min(ans, right - left + 1)
cur = gcd(prefix
# 返回结果
return ans
时间复杂度:O(nlogn) 空间复杂度:O(n)