【周赛总结】双周赛109

双周赛109

37分钟AK,T3初始值写错WA一次,满足

检查数组是否是好的【LC2784】

给你一个整数数组 nums ,如果它是数组 base[n] 的一个排列,我们称它是个 数组。

base[n] = [1, 2, ..., n - 1, n, n] (换句话说,它是一个长度为 n + 1 且包含 1n - 1 恰好各一次,包含 n 两次的一个数组)。比方说,base[1] = [1, 1]base[3] = [1, 2, 3, 3]

如果数组是一个好数组,请你返回 true ,否则返回 false

**注意:**数组的排列是这些数字按任意顺序排布后重新得到的数组。

  • 思路:排序+模拟

    排序后的好数组满足以下条件

    • i ∈ 0 , n − 2 i \in 0,n-2 i∈0,n−2时,满足 n u m s i = = i + 1 numsi==i+1 numsi==i+1
    • 最后一位满足 n u m s n − 1 = = n − 1 numsn- 1==n - 1 numsn−1==n−1

    如果符合返回true,否则返回false

  • 实现

    java 复制代码
    class Solution {
        public boolean isGood(int[] nums) {
            int n = nums.length;
            Arrays.sort(nums);
            for (int i = 0; i < n - 1; i++){
                if (i + 1 != nums[i]){
                    return false;
                }
            }
            return nums[n - 1] == n - 1;
    
        }
    }
    • 复杂度
      • 时间复杂度: O ( n log ⁡ n ) \mathcal{O}(n \log n) O(nlogn)
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)

将字符串中的元音字母排序【LC2785】

给你一个下标从 0 开始的字符串 s ,将 s 中的元素重新 排列 得到新的字符串 t ,它满足:

  • 所有辅音字母都在原来的位置上。更正式的,如果满足 0 <= i < s.length 的下标 i 处的 s[i] 是个辅音字母,那么 t[i] = s[i]
  • 元音字母都必须以他们的 ASCII 值按 非递减 顺序排列。更正式的,对于满足 0 <= i < j < s.length 的下标 ij ,如果 s[i]s[j] 都是元音字母,那么 t[i] 的 ASCII 值不能大于 t[j] 的 ASCII 值。

请你返回结果字母串。

元音字母为 'a''e''i''o''u' ,它们可能是小写字母也可能是大写字母,辅音字母是除了这 5 个字母以外的所有字母。

  • 思路:模拟+排序

    先遍历一遍字符串,统计元音字符,将其按升序排序;再遍历一遍字符串,生成结果,辅音字母直接添加进sb中,元音字母按升序添加进sb中

  • 实现

    java 复制代码
    class Solution {
        public String sortVowels(String s) {
            int n = s.length();
            StringBuilder sb = new StringBuilder();
            boolean[] isVowel = new boolean[n];
            List<Character> vowels = new ArrayList<>();
            for (int i = 0; i < n; i++){
                char c = s.charAt(i);
                if (isVowel(c)){
                    isVowel[i] = true;
                    vowels.add(c);
                }
            }
            Collections.sort(vowels, (c1, c2) -> c1 - c2);
            int j = 0;
            for (int i = 0; i < n; i++){
                if (isVowel[i]){
                    sb.append(vowels.get(j));
                    j++;
                }else{
                    sb.append(s.charAt(i));
                }
            }
            return sb.toString();
        }
        public boolean isVowel(char c){
            return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || 
                    c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
        }
    }
    • 复杂度
      • 时间复杂度: O ( n log ⁡ n ) \mathcal{O}(n\log n) O(nlogn)
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)

访问数组中的位置使分数最大【LC2786】

给你一个下标从 0 开始的整数数组 nums 和一个正整数 x

一开始 在数组的位置 0 处,你可以按照下述规则访问数组中的其他位置:

  • 如果你当前在位置 i ,那么你可以移动到满足 i < j任意 位置 j
  • 对于你访问的位置 i ,你可以获得分数 nums[i]
  • 如果你从位置 i 移动到位置 jnums[i]nums[j]奇偶性 不同,那么你将失去分数 x

请你返回你能得到的 最大 得分之和。

注意 ,你一开始的分数为 nums[0]

  • 思路:dp

    使用 d p i 0 / 1 dpi0/1 dpi0/1记录截止目前以奇数/偶数为末尾的最大分数。

    • 状态转移

      当前状态有前一个存在的状态转移得到,如果奇偶性不同,需要进行扣分

      • 如果 n u m s i numsi numsi为奇数,当前状态可以由前一个奇数状态转移,或者由前一个偶数状态转移,此时还需要扣分,保留较大值
        d p i 0 = m a x ( d p i − 1 0 , d p i − 1 1 + n u m s i − x ) dpi0=max(dpi-10,dpi-11+numsi-x) dpi0=max(dpi−10,dpi−11+numsi−x)

      • 如果 n u m s i numsi numsi为偶数,当前状态可以由前一个奇数状态转移,或者由前一个偶数状态转移,此时还需要扣分,保留较大值
        d p i 1 = m a x ( d p i − 1 1 , d p i − 1 0 + n u m s i − x ) dpi1=max(dpi-11,dpi-10+numsi-x) dpi1=max(dpi−11,dpi−10+numsi−x)

      • 1 < = n u m s i , x < = 1 0 6 1 <= numsi, x <= 10^6 1<=numsi,x<=106,设置无效状态为最小值,不会影响结果

    • 初始状态取决于 n u m s 0 nums0 nums0的奇偶性

      • 如果 n u m s 0 nums0 nums0为奇数, d p 0 0 = n u m s 0 , d p 0 1 = I n t e g e r . M I N _ V A L U E dp00=nums0,dp01=Integer.MIN\_VALUE dp00=nums0,dp01=Integer.MIN_VALUE
      • 如果 n u m s 0 nums0 nums0为偶数, d p 0 1 = n u m s 0 , d p 0 0 = I n t e g e r . M I N _ V A L U E dp01=nums0,dp00=Integer.MIN\_VALUE dp01=nums0,dp00=Integer.MIN_VALUE
  • 实现

    用变量表示

    java 复制代码
    class Solution {
        public long maxScore(int[] nums, int x) {
            long odd = Long.MIN_VALUE, even = Long.MIN_VALUE;
            int n = nums.length;
            long res = nums[0];
            if (nums[0] % 2 == 0){
                even = nums[0];
            }else{
                odd = nums[0];
            }
            for (int i = 1; i < n; i++){
                if (nums[i] % 2 == 0){
                    even = Math.max(even, even + nums[i]);
                    // if (odd != Long.MIN_VALUE){
                        even = Math.max(odd + nums[i] - x, even);
                        
                    // }   
                    res = Math.max(res, even);
                }else{
                    odd = Math.max(odd, odd + nums[i]);
                    // if (even != Long.MIN_VALUE){
                        odd = Math.max(even + nums[i] - x, odd);                
                    // }    
                    res = Math.max(res, odd);
                }
            }
            return res;
    
        }
    }
    • 复杂度
      • 时间复杂度: O ( n ) \mathcal{O}(n) O(n)
      • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

将一个数字表示成幂的和的方案数【LC2787】

给你两个 整数 nx

请你返回将 n 表示成一些 互不相同 正整数的 x 次幂之和的方案数。换句话说,你需要返回互不相同整数 [n1, n2, ..., nk] 的集合数目,满足 n = n1x + n2x + ... + nkx

由于答案可能非常大,请你将它对 109 + 7 取余后返回。

比方说,n = 160x = 3 ,一个表示 n 的方法是 n = 23 + 33 + 53

  • 思路:01背包

    • 我们能够取的数字为「小于等于 n n n的正整数的 x 次幂」,需要满足的条件为「取的所有数之和为 n n n」,这些数有限并且只能取一次,因此可以转化为01背包问题
      • 物品重量为数值,价值为方案数1,求解背包容量为 n n n的总价值
      • d p j dpj dpj:数目总和为 j j j的总方案数
  • 实现

    java 复制代码
    class Solution {
        public static final int MOD = (int)(1e9 + 7);
        public int numberOfWays(int n, int x) {
            List<Integer> nums = new ArrayList<>();// 所有可能的x的幂
            int res = 0;
            for (int i = 1; Math.pow(i, x) <= n; i++){
                nums.add((int)Math.pow(i, x));
            }
            // 01背包问题,不可重复
            int[] dp = new int[n + 1];
            dp[0] = 1;
            for (int i = 0; i < nums.size(); i++){
                for (int j = n; j >= nums.get(i); j--){
                    dp[j] = (dp[j] + dp[j - nums.get(i)]) % MOD;
                }
            }
            return dp[n];
        }
    }
    • 复杂度
      • 时间复杂度: O ( n ∗ m ) \mathcal{O}(n*m) O(n∗m),m为物品个数
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)
相关推荐
写代码写到手抽筋3 小时前
5G上行DCI字段判定:端口 流数 PMI选择详解
java·算法·5g
xieliyu.3 小时前
Java算法精讲:双指针(二)
java·开发语言·算法
wayz114 小时前
Momentum:PSL(心理线指标)技术指标详解
算法·金融·数据分析·量化交易·特征工程
8Qi85 小时前
LeetCode 213:打家劫舍 II(House Robber II)—— 题解 ✅
算法·leetcode·职场和发展·动态规划
三品吉他手会点灯5 小时前
C语言学习笔记 - 44.运算符和表达式 - 运算符2 - 除法与取余运算符
c语言·开发语言·笔记·算法
乐迪信息5 小时前
乐迪信息:AI算法盒子实时识别船舶烟雾与火焰异常
大数据·人工智能·算法·安全·目标跟踪
J-Tony115 小时前
【JVM】根可达算法
jvm·算法
艾iYYY5 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法
Lsk_Smion6 小时前
力扣实训 _ [75].颜色分类 _ 杨辉三角
数据结构·算法·leetcode