• [LeetCode319周赛] 环图,最大公因数,中心扩展+DP


    [LeetCode319周赛]

    6234. 最小公倍数为 K 的子数组数目

    https://leetcode.cn/problems/number-of-subarrays-with-lcm-equal-to-k/

    给你一个整数数组 nums 和一个整数 k ,请你统计并返回 nums子数组 中满足 元素最小公倍数k 的子数组数目。

    子数组 是数组中一个连续非空的元素序列

    数组的最小公倍数 是可被所有数组元素整除的最小正整数。

    输入:nums = [3,6,2,7,1], k = 6
    输出:4
    解释:以 6 为最小公倍数的子数组是(加粗数字):

    • [3,6,2,7,1]
    • [3,6,2,7,1]
    • [3,6,2,7,1]
    • [3,6,2,7,1]

    和本题类似的题目:
    https://blog.csdn.net/qq_39906884/article/details/127474813
    https://leetcode.cn/contest/weekly-contest-316/problems/number-of-subarrays-with-gcd-equal-to-k/

    Solution

    枚举:

    • 每次循环找以当前元素为起始且满足条件的子数组数量
    class Solution {
        public int lcm(int M, int N) {
            int a = M, b = N;
            int rem;
            while (N > 0) {
                rem = M % N;
                M = N;
                N = rem;
            }
            return a * b / M;
        }
    
        public int subarrayLCM(int[] nums, int k) {
            int n = nums.length;
            int ans = 0;
            for (int i = 0; i < n; i++) {
                int LCM = 1;
                for (int j = i; j < n; j++) {
                    LCM = lcm(LCM, nums[j]);
                    // 最小公倍数只能越来越大, 当超过 k 直接 break
                    if (LCM > k) {
                        break;
                    }
                    if (LCM == k) {
                        ans++;
                    }
                }
            }
            return ans;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    6235. 逐层排序二叉树所需的最少操作数目

    https://leetcode.cn/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/

    给你一个 值互不相同 的二叉树的根节点 root

    在一步操作中,你可以选择 同一层 上任意两个节点,交换这两个节点的值。

    返回每一层按 严格递增顺序 排序所需的最少操作数目。

    节点的 层数 是该节点和根节点之间的路径的边数。

    在这里插入图片描述

    Solution(层序遍历+选择排序)

    该题的本质就是求每一层的数从无序变成有序所需要的最少交换次数

    class Solution {
        int jg(Queue<TreeNode> queue) {
            if (queue.size() == 1) {
                return 0;
            }
            int count = 0;
            TreeNode[] arr = new TreeNode[queue.size()];
            int k = 0;
            for (TreeNode node : queue) {
                arr[k++] = node;
            }
    		// 选择排序求交换次数
            for (int i = 0; i < arr.length - 1; i++) {
                int idx = i;
                int minv = arr[i].val;
                for (int j = i + 1; j < arr.length; j++) {
                    if (minv > arr[j].val) {
                        idx = j;
                        minv = arr[j].val;
                    }
                }
                if (idx != i) {
                    count++;
                    int tmp = arr[idx].val;
                    arr[idx].val = arr[i].val;
                    arr[i].val = tmp;
                }
            }
            return count;
        }
    
    
        public int minimumOperations(TreeNode root) {
            Queue<TreeNode> queue = new ArrayDeque<>();
            int ans = 0;
            queue.add(root);
            // 层序遍历
            while (!queue.isEmpty()) {
                ans += jg(queue);
                int n = queue.size();
                for (int i = 0; i < n; i++) {
                    TreeNode node = queue.poll();
                    if (node.left != null) {
                        queue.add(node.left);
                    }
                    if (node.right != null) {
                        queue.add(node.right);
                    }
                }
            }
            return ans;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    Solution(环图+层序遍历)

    每层数据只需要看与正序的对应关系会形成几个环。假设总共形成 m 个环,每层元素数为 n,每个环需要交换 环中元素个数 - 1 次才能变为正序,总共需要交换 m-n 次才能全部变为正序。

    class Solution {
        public int minimumOperations(TreeNode root) {
            Queue<TreeNode> q = new LinkedList<>();
            q.offer(root);
            int res = 0;
            while (!q.isEmpty()){
                int curLen = q.size();
                List<Integer> origin = new ArrayList<>(curLen);
                for (int i = 0; i < curLen; i++){
                    TreeNode t = q.poll();
                    origin.add(t.val);
                    if (t.left != null){
                        q.offer(t.left);
                    }
                    if (t.right != null){
                        q.offer(t.right);
                    }
                }
                
                // 找出与正序的关系
                Map<Integer, Integer> pos = new HashMap<>();
                int [] sortedArr = new int[curLen];
                for (int i = 0; i < curLen; i ++){
                    sortedArr[i] = origin.get(i);
                }
                Arrays.sort(sortedArr);
                
                for (int i = 0; i < curLen; i ++){
                    pos.put(sortedArr[i], i);
                }
                for (int i = 0; i < curLen; i ++){
                    origin.set(i, pos.get(origin.get(i)));
                }
    			
    			// 环的个数
                int circle_cnt = 0;
                boolean [] visited = new boolean[curLen];
                for (int x: origin){
                    if (visited[x] == true){
                        continue;
                    }
                    while(visited[x] == false){
                        visited[x] = true;
                        x = origin.get(x);
                    }
                    circle_cnt ++;
                }
                res += curLen - circle_cnt;
            }
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    6236. 不重叠回文子字符串的最大数目

    https://leetcode.cn/problems/maximum-number-of-non-overlapping-palindrome-substrings/

    给你一个字符串 s 和一个 整数 k

    从字符串 s 中选出一组满足下述条件且 不重叠 的子字符串:

    每个子字符串的长度 至少k
    每个子字符串是一个 回文串
    返回最优方案中能选择的子字符串的 最大 数目。

    子字符串 是字符串中一个连续的字符序列。
    在这里插入图片描述

    Solution

    参照 647. 回文子串 的官方题解,使用统一奇数长度和偶数长度两种回文串的中心扩展法

    参照:灵神的题解

    定义 dp[i] 表示 s[0..i-1]中的不重叠回文子字符串的最大数目。

    class Solution {
        public int maxPalindromes(String str, int k) {
            char[] s = str.toCharArray();
            int n = s.length;
            int[] dp = new int[n + 1];
            for (int i = 0; i < 2 * n - 1; i++) {
                int l = i / 2;
                int r = l + i % 2; // 中心扩展
    
                dp[l + 1] = Math.max(dp[l + 1], dp[l]); // 不选择 s[l] 的最大数目
    
                for (; l >= 0 && r < n && s[l] == s[r]; l--, r++) {
                    if (r - l + 1 >= k) {
                        dp[r + 1] = Math.max(dp[r + 1], dp[l] + 1);
                        break;
                    }
                }
            }
            return dp[n];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    Springboot集成shiro框架:
    java计算机毕业设计校友闲置书籍管理平台源代码+数据库+系统+lw文档
    Mqtt入门:在线调试连接阿里云
    (十)图像数据的序列与反序列化
    通过 Nginx 实现多机负载均衡
    LeetCode刷题系列 -- 39. 组合总和
    算法 - 计数排序(Counting_Sort)
    html2canvas 行内元素边框样式生成问题解决(根据文字生成图片)
    Integer对象的大小比较
    河南省文化旅游发展相关统计数据(2014-2023年)
  • 原文地址:https://blog.csdn.net/qq_39906884/article/details/127835696