[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);
    }
}

Leetcode

posted @ 2022-05-04 13:40  Jamest  阅读(27)  评论(0编辑  收藏  举报