说来惭愧,第一次参加力扣周赛。只ac了前两个题T_T,1965 / 4747。
5942. 找出 3 位偶数
回溯枚举,排除先导0,检查是否是偶数,set去重,最后排序输出。当时写复杂了,可以直接暴搜+Set去重。记录比赛时的回溯code:https://leetcode-cn.com/submissions/detail/245377484/
暴搜+Set:
import java.util.*;
class Solution {
private boolean check(int[] digits) {
for (int num : digits) {
if (num % 2 == 0) {
return true;
}
}
return false;
}
public int[] findEvenNumbers(int[] digits) {
if (!check(digits)) {
return new int[]{};
}
Set set = new HashSet<>();
for (int i = 0; i < digits.length; i++) {
for (int j = 0; j < digits.length; j++) {
for (int k = 0; k < digits.length; k++) {
if (i != j && j != k && i != k && digits[i] != 0) {
int num = digits[i] * 100 + digits[j] * 10 + digits[k];
if (num % 2 == 0) {
set.add(num);
}
}
}
}
}
return set.stream().mapToInt(Number::intValue).sorted().toArray();
}
}
5943. 删除链表的中间节点
一次遍历,让慢指针停在中点⌊n / 2⌋,即待删除节点,同时记录它的前驱节点。由于中点向下取整,fast和slow都从head开始时,n为奇数,slow在中点,fast在尾节点;n为偶数,slow在中点,fast在尾结点.next = null。故while的循环条件cover这两种情况。
class Solution {
public ListNode deleteMiddle(ListNode head) {
if (head != null && head.next == null) {
return null;
}
ListNode slow = head, fast = head;
ListNode pre = new ListNode(-1, head);
while (fast != null && fast.next != null) {
slow = slow.next;
pre = pre.next;
fast = fast.next.next;
}
pre.next = slow.next;
slow.next = null;
return head;
}
}
5944. 从二叉树一个节点到另一个节点每一步的方向
先从根节点dfs找到起点和终点,同时记录自顶向下的路径,根到起点的路径记为pathS,到终点路径记录为pathD。统计pathS和pathD的公共路径长度i,找到最近公共祖先,即第一个路径不同的位置,用U填入起点到最近公共祖先的路径,为pathS的长度和公共路径长度i的差,拼接pathD。
class Solution {
String pathS, pathD;
private void dfs(TreeNode node, int start, int dest, StringBuilder sb) {
if (node.val == start) {
pathS = sb.toString();
}
if (node.val == dest) {
pathD = sb.toString();
}
if (node.left != null) {
dfs(node.left, start, dest, sb.append("L"));
sb.deleteCharAt(sb.length() - 1);
}
if (node.right != null) {
dfs(node.right, start, dest, sb.append("R"));
sb.deleteCharAt(sb.length() - 1);
}
}
public String getDirections(TreeNode root, int startValue, int destValue) {
dfs(root, startValue, destValue, new StringBuilder());
int i = 0;
// 统计公共路径
while (i < pathS.length() && i < pathD.length() && pathS.charAt(i) == pathD.charAt(i)) {
i++;
}
// 填入start->最近公共祖先的路径
StringBuilder sb = new StringBuilder();
for (int k = 0; k < pathS.length() - i; k++) {
sb.append("U");
}
sb.append(pathD.substring(i));
return sb.toString();
}
}
5932. 合法重新排列数对
有向图欧拉回路/通路输出。
1. 有向图判断欧拉通路存在:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
2. 有向图判断欧拉回路存在:图连通,所有的顶点出度=入度。
即满足重新排列。
首先判断图是哪一种。对于第一种,选择起点开始dfs;对于第二种,任意选择一点开始dfs。
import java.util.*;
class Solution {
List res;
Map> adj;
Map degree;
private void dfs(int start) {
if (!adj.containsKey(start)) {
return;
}
while (!adj.get(start).isEmpty()) {
Integer nei = adj.get(start).poll();
dfs(nei);
res.add(new int[]{start, nei});
}
}
public int[][] validArrangement(int[][] pairs) {
adj = new HashMap<>();
degree = new HashMap<>();
res = new ArrayList<>();
for (int[] p : pairs) {
Queue tmp = adj.getOrDefault(p[0], new LinkedList<>());
tmp.add(p[1]);
adj.put(p[0], tmp);
degree.put(p[0], degree.getOrDefault(p[0], 0) - 1);
degree.put(p[1], degree.getOrDefault(p[1], 0) + 1);
}
for (Integer key : degree.keySet()) {
if (degree.get(key) == -1) {
dfs(key);
}
}
if (res.size() == 0) {
dfs(pairs[0][0]);
}
int[][] ret = new int[res.size()][2];
int i = res.size() - 1;
for (int[] p : res) {
ret[i--] = p;
}
return ret;
}
}
下次周赛加油。