[Leetcode Weekly Contest]319

链接:LeetCode

[Leetcode]2469. 温度转换

给你一个四舍五入到两位小数的非负浮点数 celsius 来表示温度,以 摄氏度(Celsius)为单位。
你需要将摄氏度转换为 开氏度(Kelvin)和 华氏度(Fahrenheit),并以数组 ans = [kelvin, fahrenheit] 的形式返回结果。
返回数组 ans 。与实际答案误差不超过 10-5 的会视为正确答案。
注意:
开氏度 = 摄氏度 + 273.15
华氏度 = 摄氏度 * 1.80 + 32.00

按题意模拟即可。

class Solution {
    public double[] convertTemperature(double celsius) {
        double[] res = new double[2];
        res[0] = celsius + 273.15;
        res[1] = celsius * 1.8 + 32;
        return res;
    }
}

[Leetcode]2470. 最小公倍数为 K 的子数组数目

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 nums 的 子数组 中满足 元素最小公倍数为 k 的子数组数目。
子数组 是数组中一个连续非空的元素序列。
数组的最小公倍数 是可被所有数组元素整除的最小正整数。

遍历即可,注意两数乘积=最大公约数*最小公倍数。

class Solution {
    public int subarrayLCM(int[] nums, int k) {
        int n = nums.length;
        int res = 0;
        for(int i=0;i<n;++i) {
            int p = nums[i];
            for(int j=i;j<n;++j) {
                int g = gcd(p, nums[j]);
                p = p * nums[j] / g;
                if(p == k) res ++;
                if(p > k) break;
            }
        }
        return res;
    }

    public int gcd(int p, int q) {
        return q == 0 ? p : gcd(q, p%q);
    }
}

[Leetcode]2471. 逐层排序二叉树所需的最少操作数目

给你一个 值互不相同 的二叉树的根节点 root 。
在一步操作中,你可以选择 同一层 上任意两个节点,交换这两个节点的值。
返回每一层按 严格递增顺序 排序所需的最少操作数目。
节点的 层数 是该节点和根节点之间的路径的边数。

本题可以分解下面两个小问题:

  • 为层序遍历提取出每层所含的节点值
  • 对每层节点计算得到完全递增结果的需要的最小交换次数
/**
 * 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 int minimumOperations(TreeNode root) {
        ArrayDeque<TreeNode> queue = new ArrayDeque<>();
        queue.offer(root);
        int res = 0;
        while(queue.size()!=0) {
            int size = queue.size();
            int[] nums = new int[size];
            for(int i=0;i<size;++i) {
                var node = queue.poll();
                nums[i] = node.val;
                if(node.left!=null) {
                    queue.offer(node.left);
                }
                if (node.right!=null) {
                    queue.offer(node.right);
                }
            }
            res += getMinimumOperations(nums);
        }
        return res;
    }

    public int getMinimumOperations(int[] nums) {
        int res = 0, n = nums.length;
        if(n == 0) return res;
        int[] sortedNums = Arrays.copyOf(nums, n);
        Arrays.sort(nums);
        HashMap<Integer, Integer> hash = new HashMap<>();
        for(int i=0;i<n;++i) hash.put(nums[i], i);
        for(int i=0;i<n;++i) {
            if(nums[i] != sortedNums[i]) {
                var index = hash.get(sortedNums[i]);
                hash.put(nums[index], i);
                hash.put(nums[i], index);
                swap(nums, i, index);
                res ++;
            }
        }
        return res;
    }

    public void swap(int[] nums, int i, int j) {
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
}

[Leetcode]2472. 不重叠回文子字符串的最大数目

给你一个字符串 s 和一个 正 整数 k 。
从字符串 s 中选出一组满足下述条件且 不重叠 的子字符串:

  • 每个子字符串的长度 至少 为 k 。
  • 每个子字符串是一个 回文串 。

返回最优方案中能选择的子字符串的 最大 数目。
子字符串 是字符串中一个连续的字符序列。

求出每个子串是不是回文子串。记 \(g(l,r)\) 表示第 l 到 r 个字符构成的子串是不是回文子串。
之后维护 f(i) 表示长度为 的前缀中能选出多少个长度大等于 k 且不重叠的子串,转移方程为

\[f(i) = \max \begin{cases} f(i - 1) & \\ f(j) + 1 & \text{if } i - j \ge k \text{ and } g(j + 1, i) = \text{true} \end{cases} \]

上面的转移表示不选择以第 i 个字符为结尾的子串;下面的转移表示选择以第(j+1) 个字符为开始,第i个字符为结束的回文子串。
初值 \(f(0)=0\),答案就是 \(f(n)\),复杂度 \(\mathcal{O}(n^2)\)

class Solution {
    public int maxPalindromes(String s, int k) {
        int n = s.length();
        if(k==1) return n;
        int[] dp = new int[n+1];
        for(int i=0;i<n;++i) {
            dp[i+1] = dp[i];
            for(int j=i-k+1;j>=0;--j) {
                if(isPalindrome(s.substring(j,i+1))) {
                    dp[i+1] = Math.max(dp[i+1], dp[j] + 1);
                    break;
                }
            }
        }
        return dp[n];
    }

    public boolean isPalindrome(String s) {
        int i = 0, j = s.length()-1;
        while(i < j) {
            if(s.charAt(i) != s.charAt(j)) return false;
            i++;
            j--;
        }
        return true;
    }
}

参考:LeetCode

posted @ 2022-11-14 20:48  Jamest  阅读(74)  评论(0编辑  收藏  举报