leetcode第267周赛记录

  • 买票需要的时间

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

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

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

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

提示:

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

思路:排在k前的人:

​ 如果想购买的票数大于tickets[k],在k买完前会买tickets[k]张票;

​ 如果想购买的票数小于等于tickets[k],在k买完前会买tickets[i]张票;

​ k买tickets[k]张票

​ k之后的人 :

​ 如果想购买的票数大于等于tickets[k],在k买完前会买tickets[k]-1张票;

​ 如果想购买的票数小于tickets[k],在k买完前会买tickets[i]张票;

时间复杂度O(n)

空间复杂度O(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int timeRequiredToBuy(int[] tickets, int k) {
int res = 0;
for (int i = 0; i < tickets.length; i++) {
if (tickets[i]>0){
if (i<=k){
res+=Math.min(tickets[i],tickets[k]);
} else {
res+=Math.min(tickets[i],tickets[k]-1);
}
}
}
return res;
}
}
  • 反转偶数长度组的节点

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

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

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

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

提示:
链表中节点数目范围是 [1, 105]
0 <= Node.val <= 105

思路:直接模拟,先计算组的长度,再判断是否反转

时间复杂度O(n)

空间复杂度O(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public ListNode reverseEvenLengthGroups(ListNode head) {
ListNode res = new ListNode();
res.next = head;
int num = 2;
while (head.next!=null){
int count = 0;
ListNode node = head;
while (node.next!=null&&count<num){
node = node.next;
count++;
}
if (count%2==0){
ListNode last = head;
head = head.next;
while (head.next!=null&&count>1){
ListNode temp = last.next;
last.next = head.next;
head.next = last.next.next;
last.next.next = temp;
count--;
}
}else{
while (head.next!=null&&count>0){
head = head.next;
count--;
}
}
num++;
}
return res.next;
}
}
  • 解码斜向换位密码

    字符串 originalText 使用 斜向换位密码 ,经由 行数固定 为 rows 的矩阵辅助,加密得到一个字符串 encodedText 。

    originalText 先按从左上到右下的方式放置到矩阵中。

avatar

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

接着按行将字符附加到矩阵中,构造 encodedText 。

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

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

蓝色箭头标识 originalText 是如何放入矩阵中的,红色箭头标识形成 encodedText 的顺序。在上述例子中,encodedText = “ch ie pr” 。

给你编码后的字符串 encodedText 和矩阵的行数 rows ,返回源字符串 originalText 。

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

思路:先按行数拆分encodedText ,得到每一行,然后从(0,0…n)开始斜向下遍历,最后去掉末尾空格

时间复杂度O(n)

空间复杂度O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public String decodeCiphertext(String encodedText, int rows) {
String[] row = new String[rows];
int len = encodedText.length()/rows;
for (int i = 0; i <rows; i++) {
row[i] = encodedText.substring(0+i*len,len+i*len);
}
StringBuilder res = new StringBuilder();
for (int i = 0; i < len; i++) {
for (int j = 0; j < rows&&i+j<len; j++) {
res.append(row[j].charAt(i+j));
}
}
for (int i = res.length()-1; i >=0; i--) {
if (res.charAt(i)!=' '){
return res.substring(0,i+1);
}
}
return "";
}
}
  • 处理含限制条件的好友请求

给你一个整数 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 已经是直接朋友,那么他们之间的请求将仍然 成功 。

提示:

2 <= n <= 1000
0 <= restrictions.length <= 1000
restrictions[i].length == 2
0 <= xi, yi <= n - 1
xi != yi
1 <= requests.length <= 1000
requests[j].length == 2
0 <= uj, vj <= n - 1
uj != vj

思路:使用并查集维护朋友关系,哈希表维护敌人关系,合并并查集时,遍历每一个敌人,将敌人的root加入哈希表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Solution {
public boolean[] friendRequests(int n, int[][] restrictions, int[][] requests) {
UnionFind unionFind = new UnionFind(n);
for (int i = 0; i < restrictions.length; i++) {
unionFind.restrict(restrictions[i][0],restrictions[i][1]);
}
boolean[] res = new boolean[requests.length];
for (int i = 0; i < requests.length; i++) {
res[i] = unionFind.union(requests[i][0],requests[i][1]);
}
return res;
}
private class UnionFind {
private int[] parent;
private HashMap<Integer, HashSet<Integer>> map = new HashMap<>();
public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
map.put(i,new HashSet<>());
}
}

public int find(int index) {
if (index == parent[index]) {
return index;
}
int root = find(parent[index]);
parent[index] = root;
return root;
}

public boolean union(int index, int p) {
index = find(index);
p = find(p);
if (!map.get(index).contains(p)&&!map.get(p).contains(index)){
if (map.get(p).size()<map.get(index).size()){
index = index^p;
p = index^p;
index = index^p;
}
parent[index] = p;
int finalP = p;
map.get(index).forEach(i-> {
int num = this.find(i);
map.get(finalP).add(num);
map.get(num).add(finalP);
});
return true;
}
return false;
}
public void restrict(int p1,int p2) {
map.get(p1).add(p2);
map.get(p2).add(p1);
}
}
}