竞赛链接
今天更新一场周赛, 信息量有点大, 大家可以收藏起来慢慢看
这场周赛总体难度适中, 难度上升曲线比较平滑, 值得一试, 同学们可以根据自己实际情况阅读~
题目难度: 简单
原题链接
给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。
题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。
paths = [[“London”,“New York”],[“New York”,“Lima”],[“Lima”,“Sao Paulo”]]
“Sao Paulo”
从 “London” 出发,最后抵达终点站 “Sao Paulo” 。本次旅行的路线是 “London” -> “New York” -> “Lima” -> “Sao Paulo” 。
paths = [[“B”,“C”],[“D”,“B”],[“C”,“A”]]
“A”
所有可能的线路是:
显然,旅行终点站是 “A” 。
paths = [[“A”,“Z”]]
“Z”
class Solution:
def destCity(self, paths: List[List[str]]) -> str:
# 两个集合求差集, 一个是全部节点, 一个是有出度的节点
al, out = set(), set()
for p in paths:
al.add(p[0])
al.add(p[1])
out.add(p[0])
return (al - out).pop()
class Solution {
public:
string destCity(vector<vector<string>>& paths) {
unordered_set<string> all, out;
for (auto& entry : paths) {
all.insert(entry[0]);
all.insert(entry[1]);
out.insert(entry[0]);
}
for (auto& s : all) {
if (out.find(s) == out.end()) {
return s;
}
}
return {};
}
};
题目难度: 中等
原题链接
给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。
nums = [1,0,0,0,1,0,0,1], k = 2
true
每个 1 都至少相隔 2 个元素。
nums = [1,0,0,1,0,1], k = 2
false
第二个 1 和第三个 1 之间只隔了 1 个元素。
nums = [1,1,1,1,1], k = 0
true
class Solution:
def kLengthApart(self, nums: List[int], k: int) -> bool:
# 记录上一个1的下标即可, 注意下标之差要大于k+1而不是k, 因为是间隔k
last1 = None
for i, n in enumerate(nums):
if n == 1:
if last1 is None or i - last1 >= k + 1:
last1 = i
else:
return False
return True
class Solution {
public:
bool kLengthApart(vector<int>& nums, int k) {
int last1 = -1;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i]) {
if (last1 >= 0 && i - last1 < k + 1) {
return false;
}
last1 = i;
}
}
return true;
}
};
题目难度: 中等
原题链接
给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
如果不存在满足条件的子数组,则返回 0 。
nums = [8,2,4,7], limit = 4
2
所有子数组如下:
因此,满足题意的最长子数组的长度为 2 。
nums = [10,1,2,4,7,2], limit = 5
4
满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。
nums = [4,2,2,2,4,4,2,2], limit = 0
3
import heapq
class Solution:
def longestSubarray(self, nums: List[int], limit: int) -> int:
l, r = 0, 0
mx, mn = [], []
res = 0
while r < len(nums):
heapq.heappush(mx, (-nums[r], r))
heapq.heappush(mn, (nums[r], r))
while -mx[0][0] - mn[0][0] > limit:
# 加上右边界后不满足要求了, 左边界一直往右移动, 直到继续满足要求
# 同时需要更新两个堆, 如果堆顶元素的下标小于等于当前左边界的话
while mx and mx[0][1] <= l:
heapq.heappop(mx)
while mn and mn[0][1] <= l:
heapq.heappop(mn)
l += 1
res = max(res, r - l + 1)
r += 1
return res
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
int res = 0;
multimap<int, int, less<int>> incr;
multimap<int, int, greater<int>> desc;
for (int l = 0, r = 0; r < nums.size(); ++r) {
incr.emplace(nums[r], r);
desc.emplace(nums[r], r);
while(desc.begin()->first - incr.begin()->first > limit) {
while (!incr.empty() && incr.begin()->second <= l) {
incr.erase(incr.begin());
}
while (!desc.empty() && desc.begin()->second <= l) {
desc.erase(desc.begin());
}
++l;
}
res = max(res, r - l + 1);
}
return res;
}
};
from collections import deque
class Solution:
def longestSubarray(self, nums: List[int], limit: int) -> int:
l, r = 0, 0
inc, desc = deque(), deque()
res = 0
while r < len(nums):
while inc and inc[-1] > nums[r]:
inc.pop()
inc.append(nums[r])
while desc and desc[-1] < nums[r]:
desc.pop()
desc.append(nums[r])
while desc[0] - inc[0] > limit:
# 加上当前右边界后不满足要求了, 左边界一直往右移动, 直到继续满足要求
# 同时需要更新两个队列, 如果队列头恰好是当前左边界的话
if inc[0] == nums[l]:
inc.popleft()
if desc[0] == nums[l]:
desc.popleft()
l += 1
res = max(res, r - l + 1)
r += 1
return res
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
int res = 0;
deque<int> incr, desc;
for (int l = 0, r = 0; r < nums.size(); ++r) {
while (!incr.empty() && incr.back() > nums[r]) {
incr.pop_back();
}
incr.push_back(nums[r]);
while (!desc.empty() && desc.back() < nums[r]) {
desc.pop_back();
}
desc.push_back(nums[r]);
while (desc.front() - incr.front() > limit) {
if (incr.front() == nums[l]) {
incr.pop_front();
}
if (desc.front() == nums[l]) {
desc.pop_front();
}
++l;
}
res = max(res, r - l + 1);
}
return res;
}
};
题目难度: 困难
原题链接
这道题的基础版本是[373] 查找和最小的 K 对数字, 如果感觉这道题有难度的话可以先从那道题入手
给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。
你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。
mat = [[1,3,11],[2,4,6]], k = 5
7
从每一行中选出一个元素,前 k 个和最小的数组分别是:
[1,2], [1,4], [3,2], [3,4], [1,6]。其中第 5 个的和是 7 。
mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7
9
从每一行中选出一个元素,前 k 个和最小的数组分别是:
[1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]。其中第 7 个的和是 9 。
mat = [[1,3,11],[2,4,6]], k = 9
17
class Solution:
def kthSmallest(self, mat: List[List[int]], k: int) -> int:
rows, cols = len(mat), len(mat[0])
sm = sum(mat[r][0] for r in range(rows))
startIndices = (0, ) * rows
q = [(sm, startIndices)]
v = {startIndices}
for i in range(2, k + 1):
cursm, indices = heapq.heappop(q)
for r in range(rows):
if indices[r] + 1 < len(mat[r]):
newCol = indices[r] + 1
newIndices = indices[:r] + (newCol, ) + indices[r + 1:]
if newIndices not in v:
newsm = cursm + mat[r][newCol] - mat[r][indices[r]]
v.add(newIndices)
heapq.heappush(q, (newsm, newIndices))
return q[0][0]
class Solution {
public:
int kthSmallest(const vector<vector<int>>& mat, int k) {
int m = mat.size();
int n = mat[0].size();
multimap<int, vector<int>> q;
set<vector<int>> visited;
int sum = 0;
for (int i = 0; i < m; ++i) {
sum += mat[i][0];
}
q.emplace(sum, vector<int>(m, 0));
visited.insert(vector<int>(m, 0));
for (int i = 2; i <= k; ++i) {
auto sum = q.begin()->first;
auto indices = q.begin()->second;
q.erase(q.begin());
for (int r = 0; r < m; ++r) {
if (++indices[r] < n) {
if (visited.find(indices) == visited.end()) {
int newSum = sum + mat[r][indices[r]] - mat[r][indices[r]-1];
q.emplace(newSum, indices);
visited.insert(indices);
}
}
--indices[r];
}
}
return q.begin()->first;
}
};
我的公众号: 每日精选算法题, 欢迎大家扫码关注~