做题体验(4)| 豆包MarsCode AI刷题

56 阅读4分钟

今天,我们来看两道中等题

题目一:最小替换子串长度

问题描述

小F得到了一个特殊的字符串,这个字符串只包含字符ASDF,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得ASDF这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。


测试样例

样例1:

输入:input = "ADDF"
输出:1

样例2:

输入:input = "ASAFASAFADDD"
输出:3

样例3:

输入:input = "SSDDFFFFAAAS"
输出:1

样例4:

输入:input = "AAAASSSSDDDDFFFF"
输出:0

样例5:

输入:input = "AAAADDDDAAAASSSS"
输出:4

大致思路:

这道题我用的滑动窗口来解题。如果不知道滑动窗口是什么的,可以看这个视频 拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili

题解:

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static int solution(String input) {
        int n = input.length();
        int target = n / 4;
        Map<Character, Integer> countMap = new HashMap<>();

        // 初始化字符计数
        for (char ch : input.toCharArray()) {
            countMap.put(ch, countMap.getOrDefault(ch, 0) + 1);
        }

        // 检查是否已经符合目标频率
        if (isBalanced(countMap, target)) {
            return 0;
        }

        // 滑动窗口寻找最小子串长度
        int left = 0, minLen = n;
        for (int right = 0; right < n; right++) {
            char rightChar = input.charAt(right);
            countMap.put(rightChar, countMap.get(rightChar) - 1);

            while (isBalanced(countMap, target)) {
                minLen = Math.min(minLen, right - left + 1);
                char leftChar = input.charAt(left);
                countMap.put(leftChar, countMap.get(leftChar) + 1);
                left++;
            }
        }

        return minLen;
    }

    // 检查当前字符计数是否满足平衡条件
    private static boolean isBalanced(Map<Character, Integer> countMap, int target) {
        for (char ch : "ASDF".toCharArray()) {
            if (countMap.getOrDefault(ch, 0) > target) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(solution("ADDF") == 1);
        System.out.println(solution("ASAFASAFADDD") == 3);
        System.out.println(solution("SSDDFFFFAAAS") == 1);
        System.out.println(solution("AAAASSSSDDDDFFFF") == 0);
        System.out.println(solution("AAAADDDDAAAASSSS") == 4);
    }
}

具体步骤

  1. 初始化字符计数:遍历整个字符串,统计每个字符的出现次数。

  2. 检查初始平衡:如果初始状态下字符频次已经平衡,直接返回0。

  3. 滑动窗口寻找最小子串

    • 使用两个指针 left 和 right 来表示窗口的左右边界。
    • 移动 right 指针,扩展窗口,并更新字符计数。
    • 当窗口内的字符计数满足平衡条件时,记录当前窗口长度,并尝试缩小窗口(移动 left 指针)。
    • 继续移动 right 指针,直到遍历完整个字符串。
  4. 返回最小子串长度

题目二:谈心猫的鱼干大分配

问题描述

在猫星球上,小R负责给一行排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:

  1. 每只猫至少得到一斤鱼干。
  2. 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。

小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干。


测试样例

样例1:

输入:n = 3, cats_levels = [1, 2, 2]
输出:4

样例2:

输入:n = 6, cats_levels = [6, 5, 4, 3, 2, 16]
输出:17

样例3:

输入:n = 20, cats_levels = [1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4]
输出:35

题解:

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static int solution(int n, List<Integer> cats_levels) {
        int[] fishDry = new int[n];

        for (int i = 0; i < n; i++) {
            fishDry[i] = 1;
        }

        for (int i = 1; i < n; i++) {
            if (cats_levels.get(i) > cats_levels.get(i - 1)) {
                fishDry[i] = fishDry[i - 1] + 1;
            }
        }

        for (int i = n - 2; i >= 0; i--) {
            if (cats_levels.get(i) > cats_levels.get(i + 1)) {
                fishDry[i] = Math.max(fishDry[i], fishDry[i + 1] + 1);
            }
        }

        int totalFishDry = 0;
        for (int fish : fishDry) {
            totalFishDry += fish;
        }

        return totalFishDry;
    }

    public static void main(String[] args) {
        List<Integer> catsLevels1 = new ArrayList<>();
        catsLevels1.add(1);
        catsLevels1.add(2);
        catsLevels1.add(2);

        List<Integer> catsLevels2 = new ArrayList<>();
        catsLevels2.add(6);
        catsLevels2.add(5);
        catsLevels2.add(4);
        catsLevels2.add(3);
        catsLevels2.add(2);
        catsLevels2.add(16);

        List<Integer> catsLevels3 = new ArrayList<>();
        catsLevels3.add(1);
        catsLevels3.add(2);
        catsLevels3.add(2);
        catsLevels3.add(3);
        catsLevels3.add(3);
        catsLevels3.add(20);
        catsLevels3.add(1);
        catsLevels3.add(2);
        catsLevels3.add(3);
        catsLevels3.add(3);
        catsLevels3.add(2);
        catsLevels3.add(1);
        catsLevels3.add(5);
        catsLevels3.add(6);
        catsLevels3.add(6);
        catsLevels3.add(5);
        catsLevels3.add(5);
        catsLevels3.add(7);
        catsLevels3.add(7);
        catsLevels3.add(4);

        System.out.println(solution(3, catsLevels1) == 4);
        System.out.println(solution(6, catsLevels2) == 17);
        System.out.println(solution(20, catsLevels3) == 35);
    }
}

具体步骤:

  1. 初始分配

    • 每只猫至少得到一斤鱼干,所以首先将 fishDry 数组的所有元素初始化为 1。
  2. 从左到右遍历

    • 从第二只猫开始,如果当前猫的等级高于前一只猫,则当前猫的鱼干数量应比前一只猫多 1。
  3. 从右到左遍历

    • 从倒数第二只猫开始,如果当前猫的等级高于后一只猫,则当前猫的鱼干数量应比后一只猫多 1,但要确保不小于当前已分配的鱼干数量。
  4. 计算总数

    • 最后,计算 fishDry 数组中所有元素的和,即为所需的最少鱼干总数。