LeetCode 第 187 场周赛(1336/3107,前43.0%)
发布日期:2021-07-01 03:25:05 浏览次数:2 分类:技术文章

本文共 7773 字,大约阅读时间需要 25 分钟。

文章目录

1. 比赛结果

全国排名:1336 / 3107,43.0%;全球排名:5345 / 12349,43.3%

在这里插入图片描述
在这里插入图片描述

2. 题目

1. LeetCode 5400. 旅行终点站 easy

给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。
请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。

题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。

示例 1:输入:paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]输出:"Sao Paulo" 解释:从 "London" 出发,最后抵达终点站 "Sao Paulo" 。本次旅行的路线是 "London" -> "New York" -> "Lima" -> "Sao Paulo" 。示例 2:输入:paths = [["B","C"],["D","B"],["C","A"]]输出:"A"解释:所有可能的线路是:"D" -> "B" -> "C" -> "A". "B" -> "C" -> "A". "C" -> "A". "A". 显然,旅行终点站是 "A" 。示例 3:输入:paths = [["A","Z"]]输出:"Z" 提示:1 <= paths.length <= 100paths[i].length == 21 <= cityAi.length, cityBi.length <= 10cityAi != cityBi所有字符串均由大小写英文字母和空格字符组成。

解答:

class Solution {
public: string destCity(vector
>& paths) {
unordered_set
dist; unordered_set
start; for(auto p : paths) {
start.insert(p[0]);//加入起点 if(dist.count(p[0]))//目的地包含出发 dist.erase(p[0]);//删除 if(!start.count(p[1]))//不是起点 dist.insert(p[1]);//插入终点集合 else//p[1]是起点 {
if(dist.count(p[1])) dist.erase(p[1]);//终点中删除 } } return *dist.begin(); }};

32 ms 11.6 MB


赛后另解:图的出入度概念,终点,只有入度,出度为0

class Solution {
public: string destCity(vector
>& paths) {
unordered_map
in; unordered_map
out; for(auto p : paths) {
out[p[0]]++; in[p[1]]++; } for(auto in_ : in) {
if(out[in_.first]==0) return in_.first; } return ""; }};

2. LeetCode 5401. 是否所有 1 都至少相隔 k 个元素 medium

给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。
如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。

示例 1:

在这里插入图片描述

输入:nums = [1,0,0,0,1,0,0,1], k = 2输出:true解释:每个 1 都至少相隔 2 个元素。示例 2:输入:nums = [1,0,0,1,0,1], k = 2输出:false解释:第二个 1 和第三个 1 之间只隔了 1 个元素。示例 3:输入:nums = [1,1,1,1,1], k = 0输出:true示例 4:输入:nums = [0,1,0,1], k = 1输出:true 提示:1 <= nums.length <= 10^50 <= k <= nums.lengthnums[i] 的值为 0 或 1

解答:

  • 先把 1 的位置存下来,然后再遍历位置,检查相邻的差值
class Solution {
public: bool kLengthApart(vector
& nums, int k) {
bool flag = true; int i, count = 0, prev = -1; vector
pos; for(i = 0; i < nums.size(); ++i) {
if(nums[i] == 1) pos.push_back(i); } for(i = 0; i < int(pos.size())-1; ++i) {
if(pos[i+1]-pos[i] <= k) {
flag = false; break; } } return flag; }};

176 ms 60.2 MB


或者直接遍历,节省空间,

class Solution {
public: bool kLengthApart(vector
& nums, int k) {
int i, prevOneIdx = -1000000; for(i = 0; i < nums.size(); ++i) {
if(nums[i] == 1) {
if(i-prevOneIdx <= k) return false; prevOneIdx = i; } } return true; }};

184 ms 57.6 MB

3. LeetCode 5402. 绝对差不超过限制的最长连续子数组 medium

给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。

如果不存在满足条件的子数组,则返回 0 。

示例 1:输入:nums = [8,2,4,7], limit = 4输出:2 解释:所有子数组如下:[8] 最大绝对差 |8-8| = 0 <= 4.[8,2] 最大绝对差 |8-2| = 6 > 4. [8,2,4] 最大绝对差 |8-2| = 6 > 4.[8,2,4,7] 最大绝对差 |8-2| = 6 > 4.[2] 最大绝对差 |2-2| = 0 <= 4.[2,4] 最大绝对差 |2-4| = 2 <= 4.[2,4,7] 最大绝对差 |2-7| = 5 > 4.[4] 最大绝对差 |4-4| = 0 <= 4.[4,7] 最大绝对差 |4-7| = 3 <= 4.[7] 最大绝对差 |7-7| = 0 <= 4. 因此,满足题意的最长子数组的长度为 2 。示例 2:输入:nums = [10,1,2,4,7,2], limit = 5输出:4 解释:满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。示例 3:输入:nums = [4,2,2,2,4,4,2,2], limit = 0输出:3 提示:1 <= nums.length <= 10^51 <= nums[i] <= 10^90 <= limit <= 10^9

解题:

  • 双指针,滑动窗口,窗口内的数为了快速获取最大最小值,采用multimap存储
  • 一旦加入的数跟MAX,MIN做差,不在范围内,左端点向右移动,并删除map内的该值
class Solution {
public: int longestSubarray(vector
& nums, int limit) {
multimap
m;//value, idx int i = 0, j, MAX, MIN, maxlen = 1; for(j = 0; j < nums.size(); ++j) {
m.insert(make_pair(nums[j],j)); MIN = m.begin()->first;//map有序 MAX = (--m.end())->first; if(abs(nums[j]-MIN) <= limit && abs(nums[j]-MAX) <= limit) {
maxlen = max(maxlen, int(m.size())); } while(!(abs(nums[j]-MIN) <= limit && abs(nums[j]-MAX) <= limit)) {
auto it = m.lower_bound(nums[i++]); m.erase(it); MIN = m.begin()->first; MAX = (--m.end())->first; } } return maxlen; }};

276 ms 47.1 MB


参考 大佬的解:

自己写了下,采用map计数的方式

class Solution {
public: int longestSubarray(vector
& nums, int limit) {
map
m;//value, count计数 int i = 0, j = 0, MAX, MIN, maxlen = 1; while(j < nums.size()) {
m[nums[j]]++;//计数 MIN = m.begin()->first; MAX = (--m.end())->first; if(abs(nums[j]-MIN) <= limit && abs(nums[j]-MAX) <= limit) maxlen = max(maxlen, j-i+1); else {
while(!(abs(nums[j]-MIN) <= limit && abs(nums[j]-MAX) <= limit)) {
m[nums[i]]--; if(m[nums[i]]==0) m.erase(nums[i]); i++; MIN = m.begin()->first; MAX = (--m.end())->first; } } j++; } return maxlen; }};

232 ms 39 MB

4. LeetCode 5403. 有序矩阵中的第 k 个最小数组和 hard

给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。

你可以从每一行中选出 1 个元素形成一个数组。

返回所有可能数组中的第 k 个 最小 数组和。

示例 1:输入:mat = [[1,3,11],[2,4,6]], k = 5输出:7解释:从每一行中选出一个元素,前 k 个和最小的数组分别是:[1,2], [1,4], [3,2], [3,4], [1,6]。其中第 5 个的和是 7 。  示例 2:输入:mat = [[1,3,11],[2,4,6]], k = 9输出:17示例 3:输入: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 。 示例 4:输入:mat = [[1,1,10],[2,2,9]], k = 7输出:12提示:m == mat.lengthn == mat.length[i]1 <= m, n <= 401 <= k <= min(200, n ^ m)1 <= mat[i][j] <= 5000mat[i] 是一个非递减数组

解答:

参考 的解答:

  • 暴力解法
  • 把第一行跟第二行,两两相加,取最小的 k 个出来
  • 把这些再跟第三行两两相加,重复下去
class Solution {
public: int kthSmallest(vector
>& mat, int k) {
vector
ans(mat[0]); int i, j, ki; for(i = 1; i < mat.size(); ++i) {
multiset
s; for(j = 0; j < mat[i].size(); ++j) {
for(ki = 0; ki < ans.size(); ++ki) s.insert(mat[i][j]+ans[ki]); } ans.assign(s.begin(),s.end()); ans.resize(min(k, int(ans.size()))); } return ans[k-1]; }};

1736 ms 156.3 MB


优先队列解题

在这里插入图片描述

struct cmp{
bool operator()(const pair
>& a, const pair
>& b) const {
return a.first > b.first;//小顶堆,和小的在堆顶 }};class Solution {
public: int kthSmallest(vector
>& mat, int k) { pair
> tp; int i, j, s0 = 0, m = mat.size(), n = mat[0].size(), s; for(i = 0; i < m; ++i) s0 += mat[i][0];//最小的和 vector
idx(m,0);//每行选取的下标 vector
tempidx; priority_queue
>, vector
>>,cmp> q; q.push({ s0,idx}); set
> visited; visited.insert(idx);//访问过了 while(--k) { tp = q.top(); s0 = tp.first; idx = tp.second; q.pop(); for(i = 0; i < m; ++i) { tempidx = idx; tempidx[i]++;//该行变大一点 if(tempidx[i] < n && !visited.count(tempidx))//没有访问过该状态 { s = s0-mat[i][idx[i]]+mat[i][idx[i]+1];//DP思路求解下一次的和 visited.insert(tempidx); q.push({ s,tempidx}); } } } return q.top().first; }};

568 ms 43.4 MB

转载地址:https://michael.blog.csdn.net/article/details/105903207 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:LeetCode 1201. 丑数 III(最小公倍数+二分查找)
下一篇:LeetCode 第 25 场双周赛(718/1832,前39.2%)

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年05月02日 03时27分13秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

SQL优化--大数据量模糊查询缓慢 2019-05-03
Linux安装Zookeeper(Centos7) 2019-05-03
ACM进阶计划(来自于南阳理工学院) 2019-05-03
Scala学习第八天 Scala主构造器、私有构造器、构造器重载实战详解 2019-05-03
Scala学习第九天 Scala的内部类实战详解 2019-05-03
Scala学习第十天 Scala单例对象、伴生对象实战详解 2019-05-03
Scala学习第十一天 Scala中的apply实战详解 2019-05-03
Scala学习第七天 Scala类的属性和对象私有字段实战详解 2019-05-03
Scala学习第六天 Map、Tuple、Zip实战解析 2019-05-03
Scala学习第四天 Scala的For与Function进阶实战、Lazy的使用 2019-05-03
Scala学习第三天 Tuple、Array、May与文件操作入门实战 2019-05-03
Scala学习第二天 Scala函数定义、流程控制、异常处理 2019-05-03
Scala学习第五天 Scala数组操作实战详解 2019-05-03
基于key-value的存储系统Redis 2019-05-03
Scala学习第十二天 Scala中的继承:超类的构造、重写字段、重写方法代码实战 2019-05-03
Scala学习第十三天 抽象类、抽象字段、抽象方法 2019-05-03
Scala学习第十四天 Scala中作为接口的trait、在对象中混入trait代码实战 2019-05-03
Scala学习第十五天 Scala多重继承、多重继承构造器执行顺序及AOP实现 2019-05-03
Scala学习第十六天 包的定义、包对象、包的引用、包的隐式引用代码实战 2019-05-03
Scala学习第十七天 包、类、对象、成员、伴生类、伴生对象访问权限实战彻底详解 2019-05-03