[Leetcode Weekly Contest]270
链接:LeetCode
[Leetcode]2094. 找出 3 位偶数
给你一个整数数组 digits ,其中每个元素是一个数字(0 - 9)。数组中可能存在重复元素。
你需要找出 所有 满足下述条件且 互不相同 的整数:
- 该整数由 digits 中的三个元素按 任意 顺序 依次连接 组成。
- 该整数不含 前导零
- 该整数是一个 偶数
例如,给定的 digits 是 [1, 2, 3] ,整数 132 和 312 满足上面列出的全部条件。
将找出的所有互不相同的整数按 递增顺序 排列,并以数组形式返回。
遍历即可。
class Solution {
public int[] findEvenNumbers(int[] digits) {
Set<Integer> resSet = new HashSet<>();
for(int i=0;i<digits.length;++i) {
int res1 = digits[i];
if(res1 == 0) continue;
for(int j=0;j<digits.length;++j) {
if(j==i) continue;
int res2 = res1*10+digits[j];
for(int k=0;k<digits.length;++k) {
if(k==i || k==j || (digits[k]&1)!=0) continue;
resSet.add(res2*10+digits[k]);
}
}
}
int[] res = new int[resSet.size()];
int i = 0;
for(int result:resSet) {
res[i++] = result;
}
Arrays.sort(res);
return res;
}
}
[Leetcode]2095. 删除链表的中间节点
给你一个链表的头节点 head 。删除 链表的 中间节点 ,并返回修改后的链表的头节点 head 。
长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。
对于 n = 1、2、3、4 和 5 的情况,中间节点的下标分别是 0、1、1、2 和 2 。
快慢指针,注意分情况讨论即可。
class Solution {
public ListNode deleteMiddle(ListNode head) {
if(head.next==null) return null;
ListNode dummy = head, pre=head, first=head, second =head;
for(;;) {
if(first.next==null) {
pre.next = pre.next.next;
break;
}
if(first.next.next == null ) {
second.next = second.next.next;
break;
}
pre = second;
second = second.next;
first = first.next.next;
}
return dummy;
}
}
[Leetcode]2096. 从二叉树一个节点到另一个节点每一步的方向
给你一棵 二叉树 的根节点 root ,这棵二叉树总共有 n 个节点。每个节点的值为 1 到 n 中的一个整数,且互不相同。给你一个整数 startValue ,表示起点节点 s 的值,和另一个不同的整数 destValue ,表示终点节点 t 的值。
请找到从节点 s 到节点 t 的 最短路径 ,并以字符串的形式返回每一步的方向。每一步用 大写 字母 'L' ,'R' 和 'U' 分别表示一种方向:
'L' 表示从一个节点前往它的 左孩子 节点。
'R' 表示从一个节点前往它的 右孩子 节点。
'U' 表示从一个节点前往它的 父 节点。
请你返回从 s 到 t 最短路径 每一步的方向。
深度优先搜索,难度在于如何在\(O(N)\)时空复杂度下寻找根节点到特定节点的路径。在传统的DFS算法中,我们会把路径传入参数,遍历搜索,其时空复杂度为\(O(N^2)\)。
因此,我们需要尝试从节点向上遍历直到根节点从而得到对应的路径,并反向得出目标字符串。但对于一般的二叉树数据结构,我们无法很快地得到某一个节点的父节点,因此我们需要通过深度优先搜索,利用哈希表额外维护每个节点对应的父节点。维护父节点哈希表后,我们便可以在 \(O(N)\)的时间与空间复杂度内求出根节点到特定节点的路径。在求出根节点分别到两个节点的路径后,两个节点之间的路径也就容易求了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map<TreeNode, TreeNode> parentMap = new HashMap<>();
public String getDirections(TreeNode root, int startValue, int destValue) {
TreeNode node1 = findNode(root, startValue);
TreeNode node2 = findNode(root, destValue);
TreeNode head = lowestCommonAncestor(root, node1, node2);
StringBuffer path1 = new StringBuffer();
StringBuffer path2 = new StringBuffer();
TreeNode node = node1;
while (node != head) {
path1.append('U');
node = parentMap.get(node);
}
node = node2;
while (node != head) {
TreeNode parent = parentMap.get(node);
if (node == parent.left) {
path2.append('L');
} else {
path2.append('R');
}
node = parent;
}
path2.reverse();
StringBuffer directions = new StringBuffer();
directions.append(path1);
directions.append(path2);
return directions.toString();
}
/**
* 查找二叉树中值为val的节点,并将查找过程中的(节点,其父节点)存到map
*/
public TreeNode findNode(TreeNode node, int val) {
if (node == null) {
return null;
}
if (node.val == val) {
return node;
}
TreeNode node1 = findNode(node.left, val);
if (node1 != null) {
parentMap.put(node.left, node);
return node1;
}
TreeNode node2 = findNode(node.right, val);
if (node2 != null) {
parentMap.put(node.right, node);
return node2;
}
return null;
}
/**
* 查找p和q两个节点的最近祖先节点
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == p || root == q) {
return root;
}
if (root != null) {
TreeNode lNode = lowestCommonAncestor(root.left, p, q);
TreeNode rNode = lowestCommonAncestor(root.right, p, q);
if (lNode != null && rNode != null) {
return root;
} else if (lNode == null) {
return rNode;
} else {
return lNode;
}
}
return null;
}
}
[Leetcode]2097. 合法重新排列数对
给你一个下标从 0 开始的二维整数数组 pairs ,其中 pairs[i] = [starti, endi] 。如果 pairs 的一个重新排列,满足对每一个下标 i ( 1 <= i < pairs.length )都有 endi-1 == starti ,那么我们就认为这个重新排列是 pairs 的一个 合法重新排列 。
请你返回 任意一个 pairs 的合法重新排列。
注意:数据保证至少存在一个 pairs 的合法重新排列。
有向图的欧拉通路。求解欧拉通路可以使用深度优先搜索,我们一般使用 \(\text{Hierholzer}\) 算法求解欧拉通路.对于本题而言,我们首先需要找到欧拉通路的起始节点:如果图中所有节点的入度和出度都相等,那么从任意节点开始都存在欧拉通路;如果图中存在一个节点的出度比入度恰好多 1,另一个节点的入度恰好比出度多 1,那么欧拉通路必须从前一个节点开始,到后一个节点结束。除此之外的有向图都不存在欧拉通路,本体保证了至少存在一个合法排列,因此图已经是上述的两种情况之一。
class Solution {
LinkedList<Integer> ret = new LinkedList<>();
HashMap<Integer, LinkedList<Integer>> map = new HashMap<>();
HashMap<Integer, Integer> inDegree = new HashMap<>();
public int[][] validArrangement(int[][] pairs) {
for (int[] pair : pairs) {
int out = pair[0], in = pair[1];
inDegree.put(in, inDegree.getOrDefault(in, 0) + 1);
LinkedList<Integer> list = map.getOrDefault(out, new LinkedList<>());
list.add(in);
map.put(out, list);
}
int start = pairs[0][0];
for (Map.Entry<Integer, LinkedList<Integer>> entry : map.entrySet()) {
//out list
LinkedList<Integer> outList = entry.getValue();
Integer key = entry.getKey();
Integer inValue = inDegree.getOrDefault(key, 0 );
if(inValue + 1 == outList.size()){
start = key;
break;
}
}
dfs(start);
int n = pairs.length;
int[][] ans = new int[n][2];
for(int i = 0; i < n; i++){
ans[i][0] = ret.pollLast();
ans[i][1] = ret.peekLast();
}
return ans;
}
void dfs(int start){
LinkedList<Integer> list = map.get(start);
while(list != null && !list.isEmpty()){
Integer next = list.pollLast();
dfs(next);
}
ret.add(start);
}
}