青训营X豆包MarsCode 代码详解 day5 | 豆包MarsCode AI 刷题

152 阅读7分钟

最大战力值

问题描述

小F正在设计一款手游,游戏中的角色战力值需要根据一定规则来平衡,以提升玩家的游戏体验。现在游戏中有 n 个角色,编号从 0 到 n-1。为了保证平衡性,角色战力值需要遵循以下规则:

  1. 编号为 0 的角色战力值初始为 0
  2. 每个角色的战力值必须是非负整数。
  3. 相邻角色的战力值差不能超过 1,即两个相邻角色的战力值差可以是 0+1 或 -1

除此之外,游戏策划还为某些角色设定了最大战力值。这些限制通过若干数对给出,每一个数对 limit[i] = [index, maxPower],表示编号为 index 的角色的战力值不能超过 maxPower。这些限定只会对编号不为 0 的角色生效。

你的任务是根据上述规则和限制,计算游戏中单个角色能达到的最大战力值。


测试样例

样例1:

输入:n = 3 ,m = 2 ,limit = [[1, 3], [2, 2]]
输出:2

样例2:

输入:n = 5 ,m = 3 ,limit = [[1, 1], [2, 3], [4, 3]]
输出:3

样例3:

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

解题思路

  1. 初始化最大战力值限制

    • 创建一个数组 maxPower,用于存储每个角色的最大战力值限制。
    • 对于编号为 0 的角色,其战力值固定为 0
    • 对于其他角色,初始化其最大战力值为 Integer.MAX_VALUE,表示没有限制。
  2. 处理限制条件

    • 遍历 limit 数组,更新每个角色的最大战力值限制。
  3. 动态规划

    • 使用动态规划数组 dp,其中 dp[i] 表示到达第 i 个位置时的最大战力值。
    • 初始化 dp[0] 为 0
    • 正向遍历数组,确保每个位置的战力值不小于前一个位置的战力值减 1,并且不超过当前位置的最大战力值限制。
    • 反向遍历数组,确保每个位置的战力值不小于后一个位置的战力值减 1
  4. 计算最大战力值

    • 遍历 dp 数组,找出其中的最大值,即为游戏中单个角色能达到的最大战力值。

    public static int solution(int n, int m, int[][] limit) {
        // 创建一个数组存储每个角色的最大战力值限制
        int[] maxPower = new int[n];
        for (int i = 1; i < n; i++) {
            maxPower[i] = Integer.MAX_VALUE;
        }

        // 处理限制条件
        for (int[] l : limit) {
            maxPower[l[0]] = Math.min(maxPower[l[0]], l[1]);
        }

        // dp[i]表示到达第i个位置时的最大战力值
        int[] dp = new int[n];
        dp[0] = 0; // 第一个角色战力值固定为0

        // 正向遍历:确保每个位置的战力值不小于前一个位置-1
        for (int i = 1; i < n; i++) {
            dp[i] = Math.min(dp[i - 1] + 1, maxPower[i]);
        }

        // 反向遍历:确保每个位置的战力值不小于后一个位置-1
        for (int i = n - 2; i >= 0; i--) {
            dp[i] = Math.min(dp[i], dp[i + 1] + 1);
        }

        // 找出最大战力值
        int maxValue = 0;
        for (int value : dp) {
            maxValue = Math.max(maxValue, value);
        }

        return maxValue;
    }

    public static void main(String[] args) {
        // Add your test cases here

        System.out.println(solution(3, 2, new int[][] { { 1, 3 }, { 2, 2 } }) == 2);
        System.out.println(solution(5, 3, new int[][] { { 1, 1 }, { 2, 3 }, { 4, 3 } }) == 3);
    }
}

代码解释

  1. 初始化最大战力值限制

    • maxPower[i] = Integer.MAX_VALUE; 表示初始时没有限制。
    • maxPower[0] = 0; 表示编号为 0 的角色战力值固定为 0
  2. 处理限制条件

    • maxPower[l[0]] = Math.min(maxPower[l[0]], l[1]); 更新每个角色的最大战力值限制。
  3. 动态规划

    • dp[i] = Math.min(dp[i - 1] + 1, maxPower[i]); 正向遍历,确保每个位置的战力值不小于前一个位置的战力值减 1,并且不超过当前位置的最大战力值限制。
    • dp[i] = Math.min(dp[i], dp[i + 1] + 1); 反向遍历,确保每个位置的战力值不小于后一个位置的战力值减 1
  4. 计算最大战力值

    • int maxValue = 0; 初始化最大战力值为 0
    • maxValue = Math.max(maxValue, value); 遍历 dp 数组,找出其中的最大值。

最少步数归零问题

问题描述

小R拿到了一个长度为n的数组,其中每个元素都是一个正整数。小R发现每次可以删除某个数组中某个数的一位数字,这样可以逐步将所有数字变为0。他想知道,要将数组中所有数字都变为0,最少需要多少步?

例如:对于数字 103,小R可以选择删除第1位数字,将其变为 3;或者删除第2位数字,变为 13,又或者删除第3位数字,将其变为 10。最终目标是将所有数字都删除为0。


测试样例

样例1:

输入:n = 5,a = [10, 13, 22, 100, 30]
输出:7

样例2:

输入:n = 3,a = [5, 50, 505]
输出:4

样例3:

输入:n = 4,a = [1000, 1, 10, 100]
输出:4

解题思路

  1. 将整数数组转换为字符串数组

    • 首先,我们将每个整数转换为字符串,以便于后续处理。
    • 使用String.valueOf(a[i])Integer.toString(a[i])将整数转换为字符串。
  2. 去除字符串中的'0'

    • 对于每个字符串,我们使用replace("0", "")方法去除其中的'0'。
    • 注意,replace方法返回一个新的字符串,因此需要将返回值赋值回原字符串。
  3. 计算剩余字符串的长度

    • 对于每个去除'0'后的字符串,我们计算其长度。
    • 这个长度就是将该数字变为0所需的最少步数。
  4. 累加所有字符串的长度

    • 最后,我们将所有字符串的长度累加起来,得到将数组中所有数字变为0所需的最少步数。
    public static int solution(int n, int[] a) {

        int count=0;
        String[] aString=new String[n];
        for (int i = 0; i < n; i++) {
            aString[i] = String.valueOf(a[i]); // 或者使用 aString[i] = Integer.toString(a[i]);
            aString[i]=aString[i].replace("0", "");
        }

        for (int i = 0; i < n; i++) {
            count += aString[i].length(); // 直接计算字符串长度
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[]{10, 13, 22, 100, 30}) == 7);
        System.out.println(solution(3, new int[]{5, 50, 505}) == 4);
        System.out.println(solution(4, new int[]{1000, 1, 10, 100}) == 4);
    }
}

小S的倒序索引

问题描述

小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子,小S决定使用倒排索引。倒排索引的工作原理是:每个单词都会关联一个帖子ID的列表,这些帖子包含该单词,且ID按从小到大的顺序排列。
例如,单词“夏天”可能出现在帖子1、帖子3和帖子7中,那么这个单词的倒排链就是 [1, 3, 7]。如果用户想同时找到包含“夏天”和“海滩”的帖子,小S需要找出两个倒排链的交集,且将结果按照从大到小的顺序输出。现在,给定两个单词的倒排链数组 a 和 b,请你帮助小S找出同时包含这两个单词的帖子ID,并按从大到小的顺序返回结果。


测试样例

样例1:

输入:a = [1, 2, 3, 7], b = [2, 5, 7]
输出:[7, 2]

样例2:

输入:a = [1, 4, 8, 10], b = [2, 4, 8, 10]
输出:[10, 8, 4]

样例3:

输入:a = [3, 5, 9], b = [1, 4, 6]
输出:[]

样例4:

输入:a = [1, 2, 3], b = [1, 2, 3]
输出:[3, 2, 1]

由于 a 和 b 是有序列表,我们可以利用这一特性来优化查找交集的过程。我们可以使用双指针法来遍历两个列表,从而找到交集。

算法步骤

  1. 初始化指针:

    • 使用两个指针 i 和 j,分别指向列表 a 和 b 的开始位置。
  2. 遍历列表:

    • 比较 a[i] 和 b[j]

      • 如果 a[i] 等于 b[j],则将该元素添加到结果列表中,并将两个指针都向前移动一位。
      • 如果 a[i] 小于 b[j],则将 i 向前移动一位。
      • 如果 a[i] 大于 b[j],则将 j 向前移动一位。
  3. 排序结果:

    • 由于我们需要按从大到小的顺序返回结果,可以在找到交集后使用 Collections.sort(results, Collections.reverseOrder()) 对结果列表进行排序

public class Main {
    public static List<Integer> solution(List<Integer> a, List<Integer> b) {
        List<Integer> results = new ArrayList<>();
        int i = 0, j = 0;

        // 使用双指针法查找交集
        while (i < a.size() && j < b.size()) {
            if (a.get(i).equals(b.get(j))) {
                results.add(a.get(i));
                i++;
                j++;
            } else if (a.get(i) < b.get(j)) {
                i++;
            } else {
                j++;
            }
        }

        // 对结果列表进行降序排序
        Collections.sort(results, Collections.reverseOrder());
        return results;
    }

    public static void main(String[] args) {
        System.out.println(solution(Arrays.asList(1, 2, 3, 7), Arrays.asList(2, 5, 7)).equals(Arrays.asList(7, 2)));
        System.out.println(solution(Arrays.asList(1, 4, 8, 10), Arrays.asList(2, 4, 8, 10)).equals(Arrays.asList(10, 8, 4)));
        System.out.println(solution(Arrays.asList(3, 5, 9), Arrays.asList(1, 4, 6)).equals(Collections.emptyList()));
        System.out.println(solution(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3)).equals(Arrays.asList(3, 2, 1)));
    }
}