学习笔记:Java刷题实践与心得分享
在使用豆包MarsCode AI刷题的过程中,我尝试了解决了三道题目,分别涉及动态规划、贪心算法和数据结构的灵活应用。这些题目不仅让我加深了对算法的理解,还提升了编程调试的能力。以下是我的学习方法、题目解析、知识总结和学习计划。
一、学习方法与心得
-
逐步深入,层层剖析
面对复杂题目时,不要急于写代码。先从需求出发,明确输入、输出和约束条件,再选用合适的解法。比如在“小R徒步旅行”问题中,通过动态规划分解问题,从简化模型到实现代码逐步推进,效果显著。 -
边做边思考,追求多角度优化
一道题往往有多种解法。完成初步代码后,尝试优化性能或逻辑。比如在“商品售卖最大化”问题中,我通过频率统计和贪心匹配将时间复杂度降至最低。 -
错题是宝藏,复盘是关键
错误反映了知识盲点,复盘则能加深记忆。在解决“随机播放歌单”问题时,曾因队列操作理解不当而陷入困境。通过查阅文档和调试代码,最终解决问题,掌握了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表示前一天背包中的食物数量,l与j的变化需满足背包容量限制。
代码实现:
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. 商品售卖最大化问题
问题描述:
调整货物架上商品顺序,使最多顾客能买到自己需要的商品。
解题思路:
- 贪心算法:
统计货物架商品和顾客需求商品的数量,计算两者的交集,最大化售卖数量。 - 实现步骤:
- 使用
HashMap统计每种商品的数量。 - 逐一匹配顾客需求,累加可以售卖的商品数量。
- 使用
代码实现:
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模拟队列,每次取出第一首歌,若需要移到最后则重新插入末尾。 - 实现步骤:
- 初始化歌单队列。
- 按规则循环操作,输出播放结果。
代码实现:
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的动态操作特性。
三、知识总结
- **动态规划:**多维状态建模是关键,需明确每个维度的含义及转移条件。
- **贪心算法:**频率统计和局部最优选择是解题核心。
- **队列模拟:**熟练使用
LinkedList操作,实现复杂流程的高效模拟。
四、学习计划
- 每日专攻一个主题,三题总结方法。
- 结合AI工具和错题库复习知识点。
- 多角度分析经典题目,积累优化技巧。
在刷题过程中,AI的智能反馈和工具支持让我提升了学习效率,也体会到了编程的乐趣。希望这篇笔记能为其他学习者提供帮助!