首页 > 其他分享 >[Leetcode Weekly Contest]368

[Leetcode Weekly Contest]368

时间:2023-10-23 22:13:29浏览次数:32  
标签:下标 nums int Contest 三元组 range 368 minAssignment Leetcode

链接:LeetCode

[Leetcode]2908. 元素和最小的山形三元组 I

给你一个下标从 0 开始的整数数组 nums 。
如果下标三元组 (i, j, k) 满足下述全部条件,则认为它是一个 山形三元组 :

  • i < j < k
  • nums[i] < nums[j] 且 nums[k] < nums[j]

请你找出 nums 中 元素和最小 的山形三元组,并返回其 元素和 。如果不存在满足条件的三元组,返回 -1 。
遍历循环即可。

[Leetcode]2909. 元素和最小的山形三元组 II

给你一个下标从 0 开始的整数数组 nums 。
如果下标三元组 (i, j, k) 满足下述全部条件,则认为它是一个 山形三元组 :

  • i < j < k
  • nums[i] < nums[j] 且 nums[k] < nums[j]

请你找出 nums 中 元素和最小 的山形三元组,并返回其 元素和 。如果不存在满足条件的三元组,返回 -1 。

枚举 nums[j] + 前后缀分解。知道了 \(\textit{nums}[j]\),只需要知道 j 左边的最小值和右边的最小值,就知道了三元组的和的最小值。

class Solution {
    public int minimumSum(int[] nums) {
        int n = nums.length;
        int[] left = new int[n];
        int[] right = new int[n];
        int leftMin = nums[0];
        for(int i=1;i<n;++i) {
            if(leftMin < nums[i]) {
                left[i] = leftMin;
            } else {
                left[i] = Integer.MAX_VALUE;
                leftMin = nums[i];
            }
        }
        int rightMin = nums[n-1];
        for(int i=n-2;i>=0;--i) {
            if(rightMin < nums[i]) {
                right[i] = rightMin;
            } else {
                right[i] = Integer.MAX_VALUE;
                rightMin = nums[i];
            }
        }
        int res = Integer.MAX_VALUE;
        for(int i=1;i<n-1;++i) {
            if(left[i] == Integer.MAX_VALUE || right[i] == Integer.MAX_VALUE) continue;
            res = Math.min(res, left[i] + right[i] + nums[i]);
        }
        return res == Integer.MAX_VALUE ? -1 : res;
    }
}

[Leetcode] 2910. 合法分组的最少组数

给你一个长度为 n 下标从 0 开始的整数数组 nums 。
我们想将下标进行分组,使得 [0, n - 1] 内所有下标 i 都 恰好 被分到其中一组。
如果以下条件成立,我们说这个分组方案是合法的:

  • 对于每个组 g ,同一组内所有下标在 nums 中对应的数值都相等。
  • 对于任意两个组 g1 和 g2 ,两个组中 下标数量 的 差值不超过 1 。
    请你返回一个整数,表示得到一个合法分组方案的 最少 组数。

统计每个数字的出现次数,记在哈希表中。假设可以分成大小为 \(k\) 和 \(k+1\) 的组,现在需要算出每个 \(\textit{cnt}[x]\) 最少可以分成多少组。
由于两个组中下标数量的差值不超过 1, \(k\)最大可以取\(\textit{cnt}[x]\)中的最小值,我们可以把问题分解为两个部分:
1.\(\textit{cnt}[x]\)中的数量是否可以分成大小为 \(k\) 和 \(k+1\) 的组。
2.如果能,输出最小的分组数即可,如果不能,减小\(k\)的值再判断,直到\(k\)为零,输出\(-1\)。
针对第一个问题,我们可以先假设能进行对应的分组,则必定有\(a\)个\(k\)数量的组与\(b\)个\(k+1\)数量的组,那么针对\(\textit{cnt}[x]\)中的元素y必定有:

\[a*k+b*(k+1) = y \]

\[(a+b)k+b = y \]

且\(a\),\(b\)为零或者正整数,要满足这个式子,必定有\(a+b>b\),也就是\(y/k > y\%k\)。反之,如果满足\(y/k > y\%k\),我们也必定能找到\(a*k+b*(k+1) = y\)的解。
针对第二个问题,如果需要分组的数目最小,我们必定需要尽量多分\(k+1\)的组,那么,求\(y/(k+1)\)的上界即可。

class Solution {
    public int minGroupsForValidAssignment(int[] nums) {
        Map<Integer, Integer> counter = new HashMap<>();
        for(int num:nums) {
            counter.put(num, counter.getOrDefault(num, 0) + 1);
        }
        List<Integer> set = new ArrayList<>();
        int minAssignment = Integer.MAX_VALUE;
        for(int count:counter.values()) {
            set.add(count);
            minAssignment = Math.min(minAssignment, count);
        }
        while(minAssignment > 0) {
            if(minGroups(set, minAssignment))return getMinGroups(set, minAssignment);
            else minAssignment --;
        }
        return -1;
    }

    private boolean minGroups(List<Integer> nums, int minAssignment) {
        for(int num:nums) {
            int a = num / minAssignment;
            int b = num % minAssignment;
            if(a<b) return false;
        }
        return true;
    }

    private int getMinGroups(List<Integer> nums, int minAssignment) {
        System.out.println(minAssignment);
        int res = 0;
        for(int num:nums) {
            res += Math.ceil(num*1.0/(minAssignment+1));
        }
        return res;
    }
}

[Leetcode] 2911. 得到 K 个半回文串的最少修改次数

给你一个字符串 s 和一个整数 k ,请你将 s 分成 k 个 子字符串 ,使得每个 子字符串 变成 半回文串 需要修改的字符数目最少。
请你返回一个整数,表示需要修改的 最少 字符数目。
注意:

  • 如果一个字符串从左往右和从右往左读是一样的,那么它是一个 回文串 。
  • 如果长度为 len 的字符串存在一个满足 1 <= d < len 的正整数 d ,len % d == 0 成立且所有对 d 做除法余数相同的下标对应的字符连起来得到的字符串都是 回文串 ,那么我们说这个字符串是 半回文串 。比方说 "aa" ,"aba" ,"adbgad" 和 "abab" 都是 半回文串 ,而 "a" ,"ab" 和 "abca" 不是。
  • 子字符串 指的是一个字符串中一段连续的字符序列。
factors = [[] for _ in range(201)]
for i in range(1, 201):
    for j in range(i * 2, 201, i):
        factors[j].append(i)

class Solution:
    def minimumChanges(self, s: str, steps: int) -> int:
        def f(i, j):
            l = j - i + 1
            ans = inf
            for x in factors[l]:
                res = 0
                for k in range(x):
                    substr = s[i + k:j + 1:x]
                    for idx in range(len(substr) // 2):
                        if substr[idx] != substr[-idx-1]:
                            res += 1
                ans = min(ans, res)
            return ans
        n = len(s)
        calc = [[inf] * n for _ in range(n)]
        for i in range(n):
            for j in range(i + 1, n):
                calc[i][j] = f(i, j)
        # dp[i][j] 表示 s[0] 到 s[i-1] 分为 j 个字符串需要修改的字母数量
        dp = [[inf] * (steps + 1) for _ in range(n + 1)]
        dp[0][0] = 0
        for i in range(n):
            for j in range(steps):
                if dp[i][j] < inf:
                    # 枚举新的字符串 s[i] 到 s[k],注意,所有长度为 1 的字符串不满足条件
                    for k in range(i + 1, n):
                        dp[k+1][j+1] = min(dp[k+1][j+1], dp[i][j] + calc[i][k])
        return dp[-1][-1]

参考:LeetCode

标签:下标,nums,int,Contest,三元组,range,368,minAssignment,Leetcode
From: https://www.cnblogs.com/hellojamest/p/17783605.html

相关文章

  • 【LeetCode】LCP 06.拿硬币
    描述桌上有n堆力扣币,每堆的数量保存在数组coins中。我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。示例输入:[4,2,1]输出:4解释:第一堆力扣币最少需要拿2次,第二堆最少需要拿1次,第三堆最少需要拿1次,总共4次即可拿完。限制1<=n<=41<=co......
  • LeetCode | 19. 删除链表的倒数第 N 个结点
    1相关标签链表、双指针、C语言2报错情况2.1题目给你一个链表,删除链表的倒数第n个结点,并且返回链表的头结点。2.2错误代码/***Definitionforsingly-linkedlist.*structListNode{*intval;*structListNode*next;*};*/structListNo......
  • LeetCode 1.两数之和
    题目描述给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。示例第一次提交的代码i......
  • [Leetcode] 0088. 合并两个有序数组
    88.合并两个有序数组题目描述给你两个按非递减顺序排列的整数数组 nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你合并nums2到nums1中,使合并后的数组同样按非递减顺序排列。注意:最终,合并后数组不应由函数返回,而是存储在数组nums1......
  • [Leetcode] 0824. 山羊拉丁文
    824.山羊拉丁文题目描述给你一个由若干单词组成的句子 sentence,单词间由空格分隔。每个单词仅由大写和小写英文字母组成。请你将句子转换为“山羊拉丁文(GoatLatin)”(一种类似于猪拉丁文 -PigLatin的虚构语言)。山羊拉丁文的规则如下:如果单词以元音开头('a','e','i',......
  • [Leetcode] 0821. 字符的最短距离
    821.字符的最短距离题目描述给你一个字符串s和一个字符c,且c是s中出现过的字符。返回一个整数数组answer,其中answer.length==s.length且answer[i]是s中从下标i到离它最近的字符c的距离。两个下标 i和j之间的距离为abs(i-j),其中abs是绝......
  • LeetCode 300. 最长递增子序列
    最长递增子序列题目链接:300.最长递增子序列题目描述:给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示例1:输入:nums=[10,9,2,5,3,......
  • LeetCode 376. 摆动序列
    最长递增子序列题目链接:376.摆动序列题目描述:如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为**摆动序列。**第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。例如,[1,7,4,9,2,5]是一个摆动序列,因为差值......
  • leetcode102-二叉树层序遍历
    目标:将每层的结果放在每层的集合中问题:如何将不同父节点的同层节点,例如4和6,按照顺序放在一个list中思路:4和6的关联在与它们的父节点,遍历他们的父节点时将其子节点放在一个缓存队列中,从队列中取值就能够实现目标代码:点击查看代码classSolution{publicList<List<Inte......
  • Leetcode原题 -- 螺旋矩阵相关
    第一题:54. 螺旋矩阵题目描述:给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。示例:输入:matrix=[[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]解题思路:按层遍历,如图所示,找到规律后就差不多了publicList<Integer>spiral......