5926. 买票需要的时间

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 秒。

示例 2:
输入:tickets = [5,1,1,1], k = 0
输出:8
解释:
- 第一轮,队伍中的每个人都买到一张票,队伍变为 [4, 0, 0, 0] 。
- 接下来的 4 轮,只有位置 0 的人在买票。
位置 0 的人成功买到 5 张票,用掉 4 + 1 + 1 + 1 + 1 = 8 秒。


提示:

  • n == tickets.length
  • 1 <= n <= 100
  • 1 <= tickets[i] <= 100
  • 0 <= k < n

思路:
简单的模拟题,买票,买票,买票。

  1. class Solution {
  2. public int timeRequiredToBuy(int[] tickets, int k) {
  3. int res = 0;
  4. while (tickets[k] > 0) {
  5. for (int i = 0; i < tickets.length; i++) {
  6. if (tickets[i] > 0) {
  7. tickets[i]--;
  8. res++;
  9. }
  10. if (i == k && tickets[k] == 0)
  11. break;
  12. }
  13. }
  14. return res;
  15. }
  16. }

5927. 反转偶数长度组的节点

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

  • 节点 1 分配给第一组
  • 节点 23 分配给第二组
  • 节点 456 分配给第三组,以此类推

注意,最后一组的长度可能小于或者等于 1 + 倒数第二组的长度
反转 每个 偶数 长度组中的节点,并返回修改后链表的头节点 head

示例 1:
🏆 第 267 场力扣周赛 - 图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 ,偶数,节点反转。

示例 2:
🏆 第 267 场力扣周赛 - 图2
输入:head = [1,1,0,6]
输出:[1,0,1,6]
解释:
- 第一组长度为 1 ,没有发生反转。
- 第二组长度为 2 ,节点反转。
- 最后一组长度为 1 ,没有发生反转。

示例 3:
🏆 第 267 场力扣周赛 - 图3
输入:head = [2,1]
输出:[2,1]
解释:
- 第一组长度为 1 ,没有发生反转。
- 最后一组长度为 1 ,没有发生反转。

示例 4:
输入:head = [8]
输出:[8]
解释:只有一个长度为 1 的组,没有发生反转。


提示:

  • 链表中节点数目范围是 [1, 10]
  • 0 <= Node.val <= 10

思路:
比赛的时候是直接在链表上处理的,边界真恶心!
其实可以用数组的。。。
注意:题目中的高亮部分,若最后一段也是偶数个元素的话也需要反转!

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode() {}
  7. * ListNode(int val) { this.val = val; }
  8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. * }
  10. */
  11. class Solution {
  12. public ListNode reverseEvenLengthGroups(ListNode head) {
  13. if (head == null || head.next == null)
  14. return head;
  15. ListNode p = head;
  16. int cnt = 2;
  17. while (p != null) {
  18. ListNode cur = p;
  19. int len = 0;
  20. while (len < cnt && cur.next != null) {
  21. len++;
  22. cur = cur.next;
  23. }
  24. if (len < cnt) {
  25. if (len > 0 && len % 2 == 0)
  26. p.next = reverse(p.next, null);
  27. break;
  28. }
  29. ListNode ne = cur.next, end = p.next;
  30. if (cnt % 2 == 0) {
  31. p.next = reverse(p.next, ne);
  32. end.next = ne;
  33. p = end;
  34. } else {
  35. p = cur;
  36. }
  37. cnt++;
  38. }
  39. return head;
  40. }
  41. ListNode reverse(ListNode head, ListNode end) {
  42. if (head.next == end)
  43. return head;
  44. ListNode newHead = reverse(head.next, end);
  45. head.next.next = head;
  46. head.next = null;
  47. return newHead;
  48. }
  49. }
  1. //数组实现
  2. /**
  3. * Definition for singly-linked list.
  4. * public class ListNode {
  5. * int val;
  6. * ListNode next;
  7. * ListNode() {}
  8. * ListNode(int val) { this.val = val; }
  9. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  10. * }
  11. */
  12. class Solution {
  13. public ListNode reverseEvenLengthGroups(ListNode head) {
  14. if (head == null)
  15. return head;
  16. List<ListNode> list = new ArrayList<>();
  17. ListNode p = head;
  18. while (p != null) {
  19. list.add(p);
  20. p = p.next;
  21. }
  22. int len = 1;
  23. for (int i = 0; i < list.size(); i++) {
  24. int j = i;
  25. while (j + 1 < list.size() && j - i + 1 < len) {
  26. j++;
  27. }
  28. if ((j - i + 1) % 2 == 0)
  29. reverse(list, i, j);
  30. i = j;
  31. len++;
  32. }
  33. ListNode dummy = new ListNode(-1);
  34. p = dummy;
  35. for (int i = 0; i < list.size(); i++) {
  36. p.next = list.get(i);
  37. p = p.next;
  38. }
  39. p.next = null;
  40. return dummy.next;
  41. }
  42. void reverse(List<ListNode> list, int l, int r) {
  43. while (l < r) {
  44. // int t = list.get(l).val;
  45. // list.get(l).val = list.get(r).val;
  46. // list.get(r).val = t;
  47. ListNode t = list.get(l);
  48. list.set(l, list.get(r));
  49. list.set(r, t);
  50. l++;
  51. r--;
  52. }
  53. }
  54. }

5928. 解码斜向换位密码

难度中等1收藏分享切换为英文接收动态反馈
字符串 originalText 使用 斜向换位密码 ,经由 行数固定rows 的矩阵辅助,加密得到一个字符串 encodedText
originalText 先按从左上到右下的方式放置到矩阵中。
🏆 第 267 场力扣周赛 - 图4
先填充蓝色单元格,接着是红色单元格,然后是黄色单元格,以此类推,直到到达 originalText 末尾。箭头指示顺序即为单元格填充顺序。所有空单元格用 ' ' 进行填充。矩阵的列数需满足:用 originalText 填充之后,最右侧列 不为空
接着按行将字符附加到矩阵中,构造 encodedText
🏆 第 267 场力扣周赛 - 图5
先把蓝色单元格中的字符附加到 encodedText 中,接着是红色单元格,最后是黄色单元格。箭头指示单元格访问顺序。
例如,如果 originalText = "cipher"rows = 3 ,那么我们可以按下述方法将其编码:
🏆 第 267 场力扣周赛 - 图6
蓝色箭头标识 originalText 是如何放入矩阵中的,红色箭头标识形成 encodedText 的顺序。在上述例子中,encodedText = "ch ie pr"
给你编码后的字符串 encodedText 和矩阵的行数 rows ,返回源字符串 originalText
注意:originalText 含任何尾随空格 ' ' 。生成的测试用例满足 仅存在一个 可能的 originalText

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

示例 2:
🏆 第 267 场力扣周赛 - 图7
输入:encodedText = “iveo eed l te olc”, rows = 4
输出:“i love leetcode”
解释:上图标识用于编码 originalText 的矩阵。
蓝色箭头展示如何从 encodedText 找到 originalText 。

示例 3:
🏆 第 267 场力扣周赛 - 图8
输入:encodedText = “coding”, rows = 1
输出:“coding”
解释:由于只有 1 行,所以 originalText 和 encodedText 是相同的。

示例 4:
🏆 第 267 场力扣周赛 - 图9
输入:encodedText = “ b ac”, rows = 2
输出:“ abc”
解释:originalText 不能含尾随空格,但它可能会有一个或者多个前置空格。


提示:

  • 0 <= encodedText.length <= 10
  • encodedText 仅由小写英文字母和 ' ' 组成
  • encodedText 是对某个 不含 尾随空格的 originalText 的一个有效编码
  • 1 <= rows <= 1000
  • 生成的测试用例满足 仅存在一个 可能的 originalText

思路:直接模拟即可

  1. class Solution {
  2. public String decodeCiphertext(String e, int rows) {
  3. int cols = e.length() / rows;
  4. StringBuilder sb = new StringBuilder();
  5. for (int i = 0; i < cols; i++) {
  6. int k = 0, j = i;
  7. while (k < rows && j < cols) {
  8. int idx = k * cols + j;
  9. sb.append(e.charAt(idx));
  10. k++;
  11. j++;
  12. }
  13. }
  14. while (sb.length() > 0 && sb.charAt(sb.length() - 1) == ' ')
  15. sb.deleteCharAt(sb.length() - 1);
  16. return sb.toString();
  17. }
  18. }

5929. 处理含限制条件的好友请求

给你一个整数 n ,表示网络上的用户数目。每个用户按从 0n - 1 进行编号。
给你一个下标从 0 开始的二维整数数组 restrictions ,其中 restrictions[i] = [x, y] 意味着用户 x 和用户 y 不能 成为 朋友 ,不管是 直接 还是通过其他用户 间接
最初,用户里没有人是其他用户的朋友。给你一个下标从 0 开始的二维整数数组 requests 表示好友请求的列表,其中 requests[j] = [u, v] 是用户 u 和用户 v 之间的一条好友请求。
如果 uv 可以成为 朋友 ,那么好友请求将会 成功 。每个好友请求都会按列表中给出的顺序进行处理(即,requests[j] 会在 requests[j + 1] 前)。一旦请求成功,那么对所有未来的好友请求而言, uv 将会 成为直接朋友 。
返回一个 布尔数组 result ,其中元素遵循此规则:如果第 j 个好友请求 成功 ,那么 result[j] 就是 true ;否则,为 false
注意:如果 uv 已经是直接朋友,那么他们之间的请求将仍然 成功

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

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

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


提示:

  • 2 <= n <= 1000
  • 0 <= restrictions.length <= 1000
  • restrictions[i].length == 2
  • 0 <= x, y <= n - 1
  • x != y
  • 1 <= requests.length <= 1000
  • requests[j].length == 2
  • 0 <= u, v <= n - 1
  • u != v

思路:
并查集
将每对限制用哈希表维护
处理每一个请求

  • 求两个人的根节点,若相同说明已经是一组,若不相同,用根节点的邻接域判断两个集合中的人是否有冲突,有冲突说明不能合并,否则可以合并,将人少的合并到人多的集合
  1. class Solution {
  2. int[] fa;
  3. public boolean[] friendRequests(int n, int[][] restrictions, int[][] requests) {
  4. Map<Integer, Set<Integer>> map = new HashMap<>();
  5. for (int i = 0; i < n; i++)
  6. map.put(i, new HashSet<>());
  7. for (int[] p : restrictions) {
  8. map.get(p[0]).add(p[1]);
  9. map.get(p[1]).add(p[0]);
  10. }
  11. fa = new int[n];
  12. Set<Integer>[] set = new HashSet[n];
  13. for (int i = 0; i < n; i++) {
  14. fa[i] = i;
  15. set[i] = new HashSet<>();
  16. set[i].add(i);
  17. }
  18. boolean[] res = new boolean[requests.length];
  19. int idx = 0;
  20. label: for (int[] p : requests) {
  21. int pa = find(p[0]), pb = find(p[1]);
  22. if (pa == pb) {
  23. res[idx++] = true;
  24. continue;
  25. }
  26. for (int x : set[pa]) {
  27. for (int y : set[pb]) {
  28. if (map.get(x).contains(y)) {
  29. idx++;
  30. continue label;
  31. }
  32. }
  33. }
  34. if (set[pa].size() > set[pb].size()) {
  35. fa[pb] = pa;
  36. set[pa].addAll(set[pb]);
  37. } else {
  38. fa[pa] = pb;
  39. set[pb].addAll(set[pa]);
  40. }
  41. res[idx] = true;
  42. idx++;
  43. }
  44. return res;
  45. }
  46. int find(int x) {
  47. return x == fa[x] ? x : (fa[x] = find(fa[x]));
  48. }
  49. }