[Leetcode Weekly Contest]283
链接:LeetCode
[Leetcode]2194. Excel 表中某个范围内的单元格
Excel 表中的一个单元格 (r, c) 会以字符串 \("<col><row>"\) 的形式进行表示,其中:
\(<col>\) 即单元格的列号 c 。用英文字母表中的 字母 标识。
例如,第 1 列用 'A' 表示,第 2 列用 'B' 表示,第 3 列用 'C' 表示,以此类推。
\(<row>\) 即单元格的行号 r 。第 r 行就用 整数 r 标识。
给你一个格式为 "\(<col1><row1>:<col2><row2>\)" 的字符串 s ,其中 \(<col1>\) 表示 c1 列,\(<row1>\) 表示 r1 行,\(<col2>\) 表示 c2 列,\(<row2>\) 表示 r2 行,并满足 r1 <= r2 且 c1 <= c2 。
找出所有满足 \(r1 <= x <= r2\) 且 \(c1 <= y <= c2\) 的单元格,并以列表形式返回。单元格应该按前面描述的格式用 字符串 表示,并以 非递减 顺序排列(先按列排,再按行排)。
遍历即可。
class Solution {
public List<String> cellsInRange(String s) {
var sSplit = s.split(":");
char start = sSplit[0].charAt(0), end = sSplit[1].charAt(0);
int startIndex = Integer.parseInt(String.valueOf(sSplit[0].charAt(1))),
endIndex = Integer.parseInt(String.valueOf(sSplit[1].charAt(1)));
List<String> res = new ArrayList<>();
for(char i = start; i <= end; ++i)
{
for(int j=startIndex;j<=endIndex;++j)
{
res.add(""+i+j);
}
}
return res;
}
}
[Leetcode]2195. 向数组中追加 K 个整数
给你一个整数数组 nums 和一个整数 k 。请你向 nums 中追加 k 个 未 出现在 nums 中的、互不相同 的 正 整数,并使结果数组的元素和 最小 。
返回追加到 nums 中的 k 个整数之和。
直接暴力不可取, k太大了。其实是一道贪心,考虑使结果数组的元素和 最小,添加的k必定从1开始寻找未出现的正整数。因此我们可以将数组排序,循环遍历寻找k个最小数,并通过高斯求和公式求出k个最小数的和。
class Solution {
public long minimalKSum(int[] nums, int k) {
Arrays.sort(nums);
List<Integer> numsList = new ArrayList<>();
numsList.add(0);
long res = 0;
for(var n:nums) {
numsList.add(n);
}
numsList.add(Integer.MAX_VALUE);
for (int i=1;i<numsList.size();++i) {
int cur = numsList.get(i);
int pre = numsList.get(i-1);
if(cur == pre) continue;
if (k > cur-pre-1) {
res += (long)(cur+pre) * (cur-pre-1) / 2;
k -= cur-pre-1;
} else {
res += (long)(pre+1+pre+k) * k /2;
break;
}
}
return res;
}
}
[Leetcode]2196. 根据描述创建二叉树
给你一个二维整数数组 descriptions ,其中 descriptions[i] = [parenti, childi, isLefti] 表示 parenti 是 childi 在 二叉树 中的 父节点,二叉树中各节点的值 互不相同 。此外:
如果 isLefti == 1 ,那么 childi 就是 parenti 的左子节点。
如果 isLefti == 0 ,那么 childi 就是 parenti 的右子节点。
请你根据 descriptions 的描述来构造二叉树并返回其 根节点 。
测试用例会保证可以构造出 有效 的二叉树。
哈希表。建树过程并不难,需要考虑的是在建树过程中如何确定根节点。我们可以用一个哈希表 \(\textit{isRoot}\) 维护数值与是否为根节点的映射。在遍历时,我们需要将 \(\textit{isRoot}[c]\) 设为 \(\texttt{false}\)(因为该节点有父节点);而如果 \(p\) 在 \(\textit{isRoot}\) 中不存在,则说明 \(p\) 暂时没有父节点,我们可以将 \(\textit{isRoot}[c]\) 设为 \(\texttt{true}\)。最终在遍历完成后,一定有且仅有一个元素 \(\textit{root}\) 在 \(\textit{isRoot}\) 中的数值为 \(\texttt{true}\),此时对应的 \(\textit{node}[i]\) 为二叉树的根节点。
/**
* 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 {
public TreeNode createBinaryTree(int[][] descriptions) {
HashMap<Integer,TreeNode> nodes = new HashMap<>();
HashMap<Integer, Boolean> isRoot = new HashMap<>();
for (int i=0;i<descriptions.length;++i) {
int parent = descriptions[i][0], child = descriptions[i][1], isLeft = descriptions[i][2];
if (!isRoot.containsKey(parent)) isRoot.put(parent, true);
isRoot.put(child, false);
if (!nodes.containsKey(parent)) nodes.put(parent, new TreeNode(parent));
if (!nodes.containsKey(child)) nodes.put(child, new TreeNode(child));
if (isLeft == 1) nodes.get(parent).left = nodes.get(child);
else nodes.get(parent).right = nodes.get(child);
}
int root = 0;
for(int key: isRoot.keySet()){
if(isRoot.get(key)) {
root = key;
break;
}
}
return nodes.get(root);
}
}
[Leetcode]2197. 替换数组中的非互质数
给你一个整数数组 nums 。请你对数组执行下述操作:
从 nums 中找出 任意 两个 相邻 的 非互质 数。
如果不存在这样的数,终止 这一过程。
否则,删除这两个数,并 替换 为它们的 最小公倍数(Least Common Multiple,LCM)。
只要还能找出两个相邻的非互质数就继续 重复 这一过程。
返回修改后得到的 最终 数组。可以证明的是,以 任意 顺序替换相邻的非互质数都可以得到相同的结果。
生成的测试用例可以保证最终数组中的值 小于或者等于 108 。
两个数字 x 和 y 满足 非互质数 的条件是:GCD(x, y) > 1 ,其中 GCD(x, y) 是 x 和 y 的 最大公约数 。
栈模拟。难点在于我们在遍历时,不能只判断栈顶元素与遍历元素是否非互质, 如果不是互质的话,我们要继续判断原来第二位的栈顶元素与遍历元素是否非互质, 所以在判断条件中我们需要要while循环来重复进行替换操作。
另外,最小公倍数的算法可以通过先计算最大公约数,然后将双方元素相乘再除以最大公约数即可, 为了防止溢出可以先做除法再做乘法。
class Solution {
public List<Integer> replaceNonCoprimes(int[] nums) {
Stack<Integer> res = new Stack<>();
int n = 0;
for(int i=0;i<nums.length;i++) {
res.add(nums[i]);
n++;
while (n>=2 && gcd(res.get(n-1), res.get(n-2))>1) {
int last = res.pop();
int pre = res.pop();
int gcdValue = gcd(last, pre);
res.add(last/gcdValue*pre);
n--;
}
}
return res;
}
public int gcd(int p, int q) {
if(q==0) return p;
return gcd(q, p%q);
}
}