资讯专栏INFORMATION COLUMN

LeetCode 第 267 场周赛

Dionysus_go / 2223人阅读

摘要:第三组长度为,奇数,没有发生反转。箭头指示顺序即为单元格填充顺序。因此我们采用并查集处理朋友关系。如果没有冲突,再把修改后的副本赋值给原并查集,添加成功否则就认为这个添加无法进行,原并查集对象不做修改,该请求为。

本文对267场周赛题目做一个小结。周赛题目链接在此

No 1 买票需要的时间

有 n 个人前来排队买票,其中第 0 人站在队伍 最前方 ,第 (n - 1) 人站在队伍 最后方 。

给你一个下标从 0 开始的整数数组 tickets ,数组长度为 n ,其中第 i 人想要购买的票数为 tickets[i] 。

每个人买票都需要用掉 恰好 1 秒 。一个人 一次只能买一张票 ,如果需要购买更多票,他必须走到 队尾 重新排队(瞬间 发生,不计时间)。如果一个人没有剩下需要买的票,那他将会 离开 队伍。

返回位于位置 k(下标从 0 开始)的人完成买票需要的时间(以秒为单位)。

示例 1:

输入:tickets = [2,3,2], k = 2
输出:6
解释:

  • 第一轮,队伍中的每个人都买到一张票,队伍变为 [1, 2, 1] 。
  • 第二轮,队伍中的每个都又都买到一张票,队伍变为 [0, 1, 0] 。
    位置 2 的人成功买到 2 张票,用掉 3 + 3 = 6 秒。

解析

本题是例行签到题,数据范围不大,暴力实现就可以通过。
本题给定一个数组,表示有n个人每个人购买若干张票。一个人每次只能买一张,如果还需要购买就要重新排队。每次购票耗时1s,求第k个人买完自己的票要多久。
本题按照要求直接做即可。建一个队列,将编号0~n-1依次入队,每次出队一个编号,就把该编号的购票数减一,同时计数器加1,代表这个号的人买票一张,耗时1s。如果减一之后这个编号还有票需要购买,就再次入队。直到编号为k的购票数减少至0,返回计数器的数值即可。

由于本题数据范围很小,最多100人,每人购票最多100张,最多只需10000次操作,因此暴力不会超时。如果要更快,也可以从数值角度计算排在k之前和之后的人在k买好票时分别买了几张票,再加起来即可(这样可以从 O ( N 2 ) O(N^2) O(N2) 降到 O ( N ) O(N) O(N)

C++代码如下:

//No 1  int timeRequiredToBuy(vector<int>& tickets, int k) {    queue<int>q;    int n = tickets.size(), ans = 0;    for (int i = 0; i < n; ++i) {      q.push(i);    }    while (tickets[k] > 0) {      int c = q.front();      q.pop();      tickets[c]--;      ++ans;      if (tickets[c] > 0)q.push(c);    }    return ans;  }

No 2 反转偶数长度组的节点

给你一个链表的头节点 head 。

链表中的节点 按顺序 划分成若干 非空 组,这些非空组的长度构成一个自然数序列(1, 2, 3, 4, …)。一个组的 长度 就是组中分配到的节点数目。换句话说:

节点 1 分配给第一组
节点 2 和 3 分配给第二组
节点 4、5 和 6 分配给第三组,以此类推
注意,最后一组的长度可能小于或者等于 1 + 倒数第二组的长度 。

反转 每个 偶数 长度组中的节点,并返回修改后链表的头节点 head 。

示例 1:

输入:head = [5,2,6,3,9,1,7,3,8,4]
输出:[5,6,2,3,9,1,4,8,3,7]
解释:

  • 第一组长度为 1 ,奇数,没有发生反转。
  • 第二组长度为 2 ,偶数,节点反转。
  • 第三组长度为 3 ,奇数,没有发生反转。
  • 最后一组长度为 4 ,偶数,节点反转。

解析

本题要求对链表按规则分组翻转。分组规则是,按照1,2,3,4的自然数数列递增,先选择第一个节点为1组,然后接下来2个节点一组,在之后3个节点划在一组,以此类推。最后一组很可能不够,那就剩下有多少节点就分在一组。分好组后,每组的长度就是1,2,3,4…last。last表示最后一组,其长度不一定是倒数第二组加1.然后对其中长度为偶数的每一组都做翻转,返回完成翻转后的链表。

本题其实也没什么技巧,就是按照题意去做分组,需要注意的地方是最后一组长度可能不够计划值,实际长度为偶数也需要做翻转。

考虑到链表分组翻转有很多细节要考虑,容易出错。我这里将其转化为数组,完成翻转后再构造一个新链表(题目没有说必须原地翻转)

首先将链表元素依次提出放入数组。数组下标从0开始,每次根据是否越界和当前这一组的长度,确定下一组开始位置和本组的范围与长度。如果长度是偶数,就通过swap操作交换元素实现局部的翻转。反转结束后,新建头结点,用数组元素值依次构造节点加入链表。

C++代码如下:

//No 2  ListNode* reverseEvenLengthGroups(ListNode* head) {    vector<int>l;    ListNode* p = head;    int n = 0;    while (p) {      l.push_back(p->val);      p = p->next;      ++n;    }    int i = 0,k=1;    while (i < n) {      int curL = 0;      if (i + k <= n) curL = k;      else curL = n - i;      if (curL % 2 == 0) {        for (int j = 0; j < curL / 2; ++j) {          swap(l[i + j], l[i + j + curL / 2]);        }      }      i = i + curL;      ++k;    }    ListNode* helper = new ListNode(-1);    p = helper;    for (auto v : l) {      p->next = new ListNode(v);      p = p->next;    }    return helper->next;  }

No 3 解码斜向换位密码

字符串 originalText 使用 斜向换位密码 ,经由 行数固定 为 rows 的矩阵辅助,加密得到一个字符串 encodedText 。
originalText 先按从左上到右下的方式放置到矩阵中。

先填充蓝色单元格,接着是红色单元格,然后是黄色单元格,以此类推,直到到达 originalText 末尾。箭头指示顺序即为单元格填充顺序。所有空单元格用 ’ ’ 进行填充。矩阵的列数需满足:用 originalText 填充之后,最右侧列 不为空 。

接着按行将字符附加到矩阵中,构造 encodedText 。
先把蓝色单元格中的字符附加到 encodedText 中,接着是红色单元格,最后是黄色单元格。箭头指示单元格访问顺序。

例如,如果 originalText = “cipher” 且 rows = 3 ,那么我们可以按下述方法将其编码:

蓝色箭头标识 originalText 是如何放入矩阵中的,红色箭头标识形成 encodedText 的顺序。在上述例子中,encodedText = “ch ie pr” 。
给你编码后的字符串 encodedText 和矩阵的行数 rows ,返回源字符串 originalText 。

注意:originalText 不 含任何尾随空格 ’ ’ 。生成的测试用例满足 仅存在一个 可能的 originalText 。

示例 1:

输入:encodedText = “ch ie pr”, rows = 3
输出:“cipher”
解释:此示例与问题描述中的例子相同。

解析

本题给了一种字符串加密方式,先构造一定行数的二维网格,将原字符串按照左上到右下的对角线方向逐个填充,首先从第一行第一列开始,向右下角(行数+1,列数+1)填充;然后从第一行第二列开始,以此类推。最后将二维表格逐行读取拼接成字符串,作为加密后的字符串。现在本题给定加密后的字符串以及二维网格行数,让我们解析原字符串。

实际上本题也没有什么技巧可言,由于加密后的字符串包含了二维网格所有元素(未填充按空格记录),所以我们根据其长度和行数,就可以得到这个网格的列数,进而按照逐行填充的顺序,把加密字符串的每个字符填回二维网格中,再根据原有规则,从对角线方向读取恢复原字符串。

另外本题说明原始字符串没有结尾处的空格,回复之后要将末尾空格删去。

C++代码如下:

//No 3  string decodeCiphertext(string encodedText, int rows) {    int n = encodedText.size(),cols=n/rows;    vector<vector<char>> board(rows, vector<char>(cols));    for (int i = 0; i < n; ++i) {      int r = i / cols, c = i % cols;      board[r][c] = encodedText[i];    }    string ans;    for (int i = 0; i < cols; ++i) {      int sr = 0, sc = i;      while (sr < rows && sc < cols) {        ans.push_back(board[sr][sc]);        ++sr;        ++sc;      }    }    while (ans.back() == " ") ans.pop_back();    return ans;  }

No 4 处理含限制条件的好友请求

给你一个整数 n ,表示网络上的用户数目。每个用户按从 0 到 n - 1 进行编号。

给你一个下标从 0 开始的二维整数数组 restrictions ,其中 restrictions[i] = [xi, yi] 意味着用户 xi 和用户 yi 不能 成为 朋友 ,不管是 直接 还是通过其他用户 间接 。

最初,用户里没有人是其他用户的朋友。给你一个下标从 0 开始的二维整数数组 requests 表示好友请求的列表,其中 requests[j] = [uj, vj] 是用户 uj 和用户 vj 之间的一条好友请求。

如果 uj 和 vj 可以成为 朋友 ,那么好友请求将会 成功 。每个好友请求都会按列表中给出的顺序进行处理(即,requests[j] 会在 requests[j + 1] 前)。一旦请求成功,那么对所有未来的好友请求而言, uj 和 vj 将会 成为直接朋友 。

返回一个 布尔数组 result ,其中元素遵循此规则:如果第 j 个好友请求 成功 ,那么 result[j] 就是 true ;否则,为 false 。
注意:如果 uj 和 vj 已经是直接朋友,那么他们之间的请求将仍然 成功 。

示例 1:
输入:n = 3, restrictions = [[0,1]], requests = [[0,2],[2,1]]
输出:[true,false]
解释:
请求 0 :用户 0 和 用户 2 可以成为朋友,所以他们成为直接朋友。
请求 1 :用户 2 和 用户 1 不能成为朋友,因为这会使 用户 0 和 用户 1 成为间接朋友 (1–2--0) 。

解析

本题要求我们对于编号0~n-1的n个用户,根据请求和约束确定他们之间的朋友关系,对于每个请求,如果请求的两个用户(v1,v2)建立朋友关系,就记为true,否则记为false,最后返回每个请求是否成功的数组。

这里我们需要判断和建立直接-间接朋友关系,也就是朋友关系是可以传递的。因此很容易想到采用数据结构并查集,一旦a和b建立了朋友关系,那么a和b原来各自的朋友之间也就建立了间接朋友关系。

因此我们采用并查集处理朋友关系。但是本题还有一个要求,有些用户被约束无法成为直接或间接的好友。因此,我们应当对于每一个请求,首先通过查询判断是否已经是好友了,是的话直接记录该请求结果为true;如果不是,我们要先判断将二者加为好友会不会违反一些约束,如果违反了,就记录为false并且不把这个朋友关系真的添加进去,如果不违反,再进行添加,添加后请求结果为true。

这个思路也比较简单粗暴,复杂度比较极限,正好能过。由于并查集没有删除的操作(并集之后无法还原),我这里用了很直接的方式。如果一个请求的两个用户还不是好友,就先把原并查集拷贝一份副本,在副本对象中进行添加好友关系,判断是否与约束条件有冲突。如果没有冲突,再把修改后的副本赋值给原并查集,添加成功;否则就认为这个添加无法进行,原并查集对象不做修改,该请求为false。

C++代码如下:

class UnionFind {  int n;  vector<int> parent;  vector<int> size;public:  UnionFind(int n_) {    this->n = n_;    parent = vector<int>(n);    size = vector<int>(n, 1);    for (int i = 0; i < n; ++i)      parent[i] = i;  }  int find(int idx) {    if (parent[idx] == idx)      return idx;    return find(parent[idx]);  }  void connect(int a, int b) {    int fa = find(a), fb = find(b);    if (fa != fb) {      if (size[fa] > size[fb]) {        parent[fb] = fa;        size[fa] += size[fb];      }      else {        parent[fa] = fb;        size[fb] += size[fa];      }    }  }};//No 4  vector<bool> friendRequests(int n, vector<vector<int>>& restrictions, vector<vector<int>>& requests) {    int nre = requests.size();    vector<bool>ans(nre);    UnionFind UF(n);    for (int i = 0; i < nre; ++i) {      int v1 = requests[i][0], v2 = requests[i][1];      if (UF.find(v1) == UF.find(v2)) ans[i] = true;      else {        UnionFind UFtmp = UF;        UFtmp.connect(v1, v2);        bool can = true;        for (auto r : restrictions) {          if (UFtmp.find(r[0]) == UFtmp.find(r[1])) {            can = false;            break;          }        }        ans[i] = can;        if(can) UF.connect(v1, v2);      }    }    return ans;  }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123342.html

相关文章

  • [LeetCode] 267. Palindrome Permutation II

    Problem Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form. Example Given s = aabb, return [abba,baa...

    huashiou 评论0 收藏0
  • AI Challenger开赛,千万量级数据开放,AI高手将上演巅峰对决

    摘要:月日,各项竞赛的排名将决定最终的成绩排名。选手通过训练模型,对虚拟股票走势进行预测。冠军将获得万元人民币的奖励。 showImg(https://segmentfault.com/img/bVUzA7?w=477&h=317); 2017年9月4日,AI challenger全球AI挑战赛正式开赛,来自世界各地的AI高手,将展开为期三个多月的比拼,获胜团队将分享总额超过200万人民币的...

    Ali_ 评论0 收藏0
  • LC 267 Palindrome Permutation II

    摘要:判断一个能否组成一个第一次出现增加一,第二次出现减少一。出现偶数次的最终对被抵消。出现基数词的则会让加一。类似于,奇数个的那个单独考虑,必须放中间。得到各个字符一半数量的长度数字的终止条件,利用的对称性输出结果。 Given a string s, return all the palindromic permutations (without duplicates) of it. R...

    lowett 评论0 收藏0
  • Vultr19个机房墨西哥城数据中心路由去程回程和综合速度测试

    摘要:第五墨西哥城机房路由去程测试从上面的丢包可以看到,大陆机房线路肯定不行。最近一两个月我们是不是看到Vultr服务商的动静还是蛮大的,比如前些天有新增调整新用户促销活动,居然有重新发布两年前有过的充多少送多少的活动,对于有较大的服务器需求的来说确实是比较划算的,至少一年中可以再优惠一半。同时,我们可以看到又新增第18个和第19个数据中心,这不我们看到有新增美洲墨西哥数据中心。 从位置上看...

    李文鹏 评论0 收藏0
  • yolov5中anchors设定案例详细说明

      在YOLOV5优化算法当中,根据不同的数据信息,通常会事先设定固定Anchor,接下来本文关键为大家介绍了有关yolov5中anchors设定的资料,原文中根据案例编码推荐的十分详尽,必须的小伙伴可以借鉴一下  yolov5中增强了响应式导向框(AutoLearningBoundingBoxAnchors),但是其他yolo系类是不存在的。  一、默认设置导向框  Yolov5中默认设置保留了...

    89542767 评论0 收藏0

发表评论

0条评论

Dionysus_go

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<