青训营X豆包MarsCode 技术训练营第三篇| 豆包MarsCode AI 刷题”

54 阅读4分钟

学习笔记:Java刷题实践与心得分享

在使用豆包MarsCode AI刷题的过程中,我尝试了解决了三道题目,分别涉及动态规划、贪心算法和数据结构的灵活应用。这些题目不仅让我加深了对算法的理解,还提升了编程调试的能力。以下是我的学习方法、题目解析、知识总结和学习计划。


一、学习方法与心得

  1. 逐步深入,层层剖析
    面对复杂题目时,不要急于写代码。先从需求出发,明确输入、输出和约束条件,再选用合适的解法。比如在“小R徒步旅行”问题中,通过动态规划分解问题,从简化模型到实现代码逐步推进,效果显著。

  2. 边做边思考,追求多角度优化
    一道题往往有多种解法。完成初步代码后,尝试优化性能或逻辑。比如在“商品售卖最大化”问题中,我通过频率统计和贪心匹配将时间复杂度降至最低。

  3. 错题是宝藏,复盘是关键
    错误反映了知识盲点,复盘则能加深记忆。在解决“随机播放歌单”问题时,曾因队列操作理解不当而陷入困境。通过查阅文档和调试代码,最终解决问题,掌握了LinkedList的灵活用法。


二、题目解析

1. 小R徒步旅行问题

问题描述:
小R每天需要购买足够的食物完成旅程,但背包容量有限,目标是最小化购买总成本。

解题思路:

  • 动态规划:
    定义dp[i][l]为第i天结束时,背包中剩余l份食物时的最低花费。
  • 状态转移方程:
    dp[i][l] = min(dp[i][l], dp[i - 1][j] + (l - j + 1) * data[i - 1])
    
    其中,j表示前一天背包中的食物数量,lj的变化需满足背包容量限制。

代码实现:

def solution(n, k, data):
    dp = [[float('inf')] * (k + 1) for _ in range(n + 1)]
    dp[0][0] = 0
    for i in range(1, n + 1):
        for l in range(k + 1):
            for j in range(k + 1):
                if l - j + 1 >= 0 and l - j + 1 <= k:
                    dp[i][l] = min(dp[i][l], dp[i - 1][j] + (l - j + 1) * data[i - 1])
    return dp[n][0]

心得:
这道题强化了我对动态规划的理解,特别是多维状态的使用及其转移条件的处理。


2. 商品售卖最大化问题

问题描述:
调整货物架上商品顺序,使最多顾客能买到自己需要的商品。

解题思路:

  • 贪心算法:
    统计货物架商品和顾客需求商品的数量,计算两者的交集,最大化售卖数量。
  • 实现步骤:
    1. 使用HashMap统计每种商品的数量。
    2. 逐一匹配顾客需求,累加可以售卖的商品数量。

代码实现:

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

public class Main {
    public static int solution(int n, int m, String s, String c) {
        Map<Character, Integer> ps = new HashMap<>();
        Map<Character, Integer> pc = new HashMap<>();

        for (char ch : s.toCharArray()) {
            ps.put(ch, ps.getOrDefault(ch, 0) + 1);
        }
        for (char ch : c.toCharArray()) {
            pc.put(ch, pc.getOrDefault(ch, 0) + 1);
        }

        int cnt = 0;
        for (Map.Entry<Character, Integer> entry : pc.entrySet()) {
            char k = entry.getKey();
            int v = entry.getValue();
            cnt += Math.min(ps.getOrDefault(k, 0), v);
        }

        return cnt;
    }
}

心得:
通过这道题,我学会了如何高效统计数据分布,以及贪心策略在实际问题中的应用。


3. 随机播放歌单问题

问题描述:
模拟小R的特殊播放规则,根据顺序对歌单进行操作,输出真实播放顺序。

解题思路:

  • 队列模拟:
    使用LinkedList模拟队列,每次取出第一首歌,若需要移到最后则重新插入末尾。
  • 实现步骤:
    1. 初始化歌单队列。
    2. 按规则循环操作,输出播放结果。

代码实现:

import java.util.Arrays;
import java.util.LinkedList;

public class Main {
    public static int[] solution(int n, int[] a) {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            list.add(a[i]);
        }

        int[] result = new int[n];
        int count = 0;
        int index = 0;
        while (!list.isEmpty()) {
            if (count % 2 == 0) {
                result[index] = list.getFirst();
                list.removeFirst();
                index++;
            } else {
                int temp = list.getFirst();
                list.removeFirst();
                list.addLast(temp);
            }
            count++;
        }
        return result;
    }
}

心得:
该题让我理解了如何通过数据结构高效模拟操作过程,尤其是LinkedList的动态操作特性。


三、知识总结

  1. **动态规划:**多维状态建模是关键,需明确每个维度的含义及转移条件。
  2. **贪心算法:**频率统计和局部最优选择是解题核心。
  3. **队列模拟:**熟练使用LinkedList操作,实现复杂流程的高效模拟。

四、学习计划

  1. 每日专攻一个主题,三题总结方法。
  2. 结合AI工具和错题库复习知识点。
  3. 多角度分析经典题目,积累优化技巧。

在刷题过程中,AI的智能反馈和工具支持让我提升了学习效率,也体会到了编程的乐趣。希望这篇笔记能为其他学习者提供帮助!