笔试强训 Day 44:最小差值、kotori 和素因子、dd 爱科学 1.0

Day 44

最小差值

解题思路:

  • 排序+计算;
  • 注意避免溢出,得到最优解直接返回;

代码实现:

java 复制代码
import java.util.Arrays;

public class Solution {
    
    public int minDifference(int[] a) {
        Arrays.sort(a);
        // 使用 int 会溢出
        long min = Long.MAX_VALUE;

        for (int i = 1; i < a.length; i++) {
            long diff = (long) a[i] - a[i - 1];
            min = Math.min(min, diff);
            // 关键优化
            if (min == 0) {
                return 0;
            }
        }

        return (int) min;
    }
}

kotori 和素因子

解题思路:

  • 递归 + 记忆化搜索;
  • 递归搜索 numspos 的所有质数因子,定住 pos 的质数因子后,递归搜索 numspos+1 的可以选的质数因子;
  • 使用 path 记录当前 0, pos 下,numspos 选择的质数因子组合之和,找到最小的 path

代码实现:

java 复制代码
import java.util.*;

public class Main{
    
    private static int ret = 0x3f3f3f3f;
    private static int path = 0;
    private static int[] nums;
    private static int n;
    private static boolean[] used = new boolean[1010];
    
    // 判断是不是质数
    private static boolean isPrime(int num){
        if(num == 2) return true;
        for(int i = 2; i <= Math.sqrt(num); i++){
            if(num % i == 0) return false;
        }
        return true;
    }
    
    private static void dfs(int pos){
        if(pos == n){
            ret = Math.min(ret, path);
            return;
        }
        // 对当前 nums[pos] 枚举所有质数因子, 然后以此去枚举 nums[pos+1] 被约束下的组合 path
        for(int i = 2; i <= nums[pos]; i++){
            // 当前 i 是 nums[pos] 的因子,并且该因子未被使用,同时该因子是质数
            if(nums[pos] % i != 0 || used[i] || !isPrime(i)){
                continue;
            }
            used[i] = true;
            path += i;
            
            dfs(pos + 1);
            
            used[i] = false;
            path -= i;
        }
    }
    
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        nums = new int[n];
        for(int i = 0; i < n; i++) nums[i] = in.nextInt();
        
        dfs(0);
        
        System.out.println(ret == 0x3f3f3f3f ? -1 : ret);
    }
    
}

dd 爱科学 1.0

解法一:优化状态表示

解题思路:

  • 最长递增子序列 + 状态表示优化;
  • 状态表示优化:dpi 从以 i 下标对应字符为结尾的最长递增子序列,优化到dp[c] 表示当前处理范围内,以字符 c 结尾的最长非递减子序列长度。

代码实现:

java 复制代码
import java.util.*;

public class Main{
    
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        char[] s = in.next().toCharArray();
        // 关键: dp[1] 表示以 B 为结尾的最长非递减子序列
        int[] dp = new int[26];
        int max = 0;
        
        for(int i = 1; i <= n; i++){
            int cur = s[i-1] - 'A';
            // 先找出所有合法前驱中的最大长度,再加上当前字符
            int best = 0;
            for(int j = 0; j <= cur; j++){
                best = Math.max(best, dp[j]);
            }
            dp[cur] = best + 1;
            // 找到所有 dp 元素的最大值
            max = Math.max(max, dp[cur]);
        }
        System.out.println(n - max);
    }
}

解法二:贪心 + 二分

解题思路:

  • dp[k] 表示长度为 k 的非递减子序列中,最小的末尾字符。
  • 从左到右遍历每个字符 ch
  • 如果 ch >= dp[ret],说明可以直接接到末尾,长度加一。
  • 否则二分查找第一个 > ch 的位置,用 ch 替换它。
  • 由于允许相同字符,查找的是第一个严格大于 ch 的位置。
  • ret 就是最长非递减子序列长度,答案为 n - ret

时间复杂度为 O(n log n),空间复杂度为 O(n)

代码实现:

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        int n = in.nextInt();
        char[] s = in.next().toCharArray();

        // dp[i] 表示长度为 i 的非递减子序列中,最小的末尾字符
        char[] dp = new char[n + 1];

        int ret = 0;

        for (int i = 0; i < n; i++) {
            char ch = s[i];

            // 可以直接接到当前最长序列后面
            if (ret == 0 || ch >= dp[ret]) {
                dp[++ret] = ch;
            } else {
                // 查找第一个大于 ch 的位置
                int left = 1;
                int right = ret;

                while (left < right) {
                    int mid = (left + right) / 2;

                    if (dp[mid] > ch) {
                        right = mid;
                    } else {
                        left = mid + 1;
                    }
                }

                dp[left] = ch;
            }
        }

        System.out.println(n - ret);
    }
}
相关推荐
银-豆豆15 小时前
数据结构与算法-动态规划、回溯与贪心
算法·动态规划
2601_960906721 天前
具备抗弯耐磨的性能特点
大数据·人工智能·物联网·决策树·动态规划
-dzk-1 天前
【动态规划】LC 118.杨辉三角
算法·动态规划
小星星闪亮登场1 天前
2026河南萌新联赛第四场--南阳理工学院
数据结构·算法·贪心算法·动态规划·哈希算法·广度优先
aqiu1111112 天前
【算法刷题】蓝桥杯:怎么倒茶(贪心算法 + 结构体排序)
贪心·排序
Coder-magician2 天前
《代码随想录》刷题打卡day31:动态规划-背包问题part02
算法·动态规划
OuO-22 天前
笔试强训 Day 43:kotori 和抽卡(二)、ruby 和薯条、循环汉诺塔
数学·前缀和·二分查找·动态规划·排序·滑动窗口·循环汉诺塔
hanlin033 天前
动态规划专练:力扣第718、1143题
算法·leetcode·动态规划
hanlin033 天前
动态规划专练:力扣第1035、392题
算法·leetcode·动态规划