链接:LeetCode
[Leetcode]1436. 旅行终点站
给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中(paths[i] = [cityAi, cityBi])表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。
题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。
实际上只要寻找出现在终点集合而不出现在起点集合的点即可。
class Solution:
def destCity(self, paths: List[List[str]]) -> str:
starts = [x[0] for x in paths]
ends = [x[1] for x in paths]
return [x for x in ends if x not in starts][0]
[Leetcode]1437. 是否所有 1 都至少相隔 k 个元素
给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。
对于每一个1,与其左右最近的1的间距大于等于k,则保证了所有的1的间距大于等于k。所以只要顺序去查找1,然后将两个1的间距进行判断即可。只要这个过程中有两个相邻的1间距小于k就不满足题意。需要计算两个相邻的1的间距,需要知道这两个1的索引是多少,所以使用双指针pre, next分别表示一前一后两个的索引。
class Solution:
def kLengthApart(self, nums: List[int], k: int) -> bool:
if not k:return True
pre = -float('inf')
for i in range(len(nums)):
if nums[i] == 1:
if i-pre <= k:
return False
pre = i
return True
[Leetcode]1438. 绝对差不超过限制的最长连续子数组
给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
如果不存在满足条件的子数组,则返回 0 。
构造滑动窗口([l, r]), 使用双端队列或者堆维护滑动窗口内的最大值序列和最小值序列.
如果窗口内的最大值和者最小值间隔大于题目条件, 移动l,改变窗口内的最大值或者最小值
直到满足要求.不断统计窗口的长度即可。
class Solution:
def longestSubarray(self, nums: List[int], limit: int) -> int:
from collections import deque
max_ = deque()
min_ = deque()
n = len(nums)
l = 0
res = 0
for r, num in enumerate(nums):
while max_ and num > max_[-1]:
max_.pop()
max_.append(num)
while min_ and num < min_[-1]:
min_.pop()
min_.append(num)
while max_[0] - min_[0] > limit:
if nums[l] == max_[0]:
max_.popleft()
if nums[l] == min_[0]:
min_.popleft()
l += 1
if max_[0] - min_[0] <= limit:
res = max(res, r - l +1)
return res
[Leetcode]1439. 有序矩阵中的第 k 个最小数组和
给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。
你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。
最小堆。最小堆存储的是([curr_sum, pointers])二元组,pointers是指针数组,curr_sum是该pointers指向的元素的和。初始化pointers全为0,求出相应的curr_sum,并将其入堆。
重复下列步骤k次:
- 从堆中pop出curr_sum和pointers。
- 遍历pointers的每个索引,将该索引加一,求出新的和,如果没有出现过,push入堆。
以(mat = [[1,10,10],[1,4,5],[2,3,6]]),k = 7为例,初始化pointers = (0, 0, 0),curr_sum = 4,哈希表seen加入(0, 0, 0)
从堆中pop出最小和,pointers = (0, 0, 0),curr_sum = 4。新生成([13, (1, 0, 0)],[7, (0, 1, 0)],[5, (0, 0, 1)]),在seen中做好标记,然后将三者入堆。重复该步骤k次。
import heapq
class Solution:
def kthSmallest(self, mat, k: int) -> int:
m, n = len(mat), len(mat[0])
# 初始化指针
pointers = [0] * m
# 初始化heap
heap = []
curr_sum = 0
for i in range(m):
curr_sum += mat[i][0]
heapq.heappush(heap, [curr_sum, tuple(pointers)])
# 初始化seen
seen = set()
seen.add(tuple(pointers))
# 执行k次
for _ in range(k):
# 从堆中pop出curr_sum(最小数组和)和pointers(指针数组)
curr_sum, pointers = heapq.heappop(heap)
# 每个指针轮流后移一位,将new_sum(新的数组和)和new_pointers(新的指针数组)push入堆
for i, j in enumerate(pointers):
if j < n - 1:
new_pointers = list(pointers)
new_pointers[i] = j + 1
new_pointers = tuple(new_pointers)
if new_pointers not in seen:
new_sum = curr_sum + mat[i][j + 1]- mat[i][j]
heapq.heappush(heap, [new_sum, new_pointers])
seen.add(new_pointers)
return curr_sum
参考:
leetcode