leetcode
leetcode 3001 ~ 3050
打地鼠

打地鼠

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 458 ms, 内存: 38.2 MB


/*
 * 思路:
 * 1. 使用流式编程对数据进行过滤和映射。
 * 2. 使用动态规划 (DP) 数组记录最优状态。
 * 3. 最后使用流求解最大值。
 */

import java.util.stream.IntStream;

public class WhackAMoleStream {
    public int maxMoles(int[][] moles) {
        int[][][] dp = new int[1001][3][3];
        for (int[] mole : moles) {
            int t = mole[0], x = mole[1], y = mole[2];
            IntStream.range(0, 3).forEach(i -> IntStream.range(0, 3).forEach(j -> {
                int distance = Math.abs(x - i) + Math.abs(y - j);
                if (distance <= t) {
                    dp[t][x][y] = Math.max(dp[t][x][y], dp[t - distance][i][j] + 1);
                }
            }));
        }
        return IntStream.range(0, 1001).flatMap(t -> IntStream.range(0, 3).flatMap(i -> IntStream.range(0, 3).map(j -> dp[t][i][j]))).max().orElse(0);
    }
}

解释

方法:

该题解采用了动态规划的方法。首先,对特殊情况,即锤子在第0秒就能敲击到的地鼠进行处理,特别是当地鼠位于中心点(1,1)时。接着,将所有地鼠事件按时间顺序排序,并用一个动态规划数组f[i]来记录在达到第i个事件时,最多能敲击的地鼠数量。数组p_max用于快速获取前j个事件中最大的敲击数,以优化性能。在转移方程中,如果两个事件之间的时间差足够锤子从一个事件的位置移动到另一个位置,则尝试更新f[i]。这个方法综合考虑了时间和位置的约束,以达到最优解。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
在处理t=0时刻的特殊情况,如果有多只地鼠同时在不同位置出现,该如何选择优先敲击哪只地鼠?
在给定的题解中,特别处理了t=0时刻地鼠出现在(1,1)位置的情况,因为(1,1)是中心点,从任何其他位置移动到中心点的距离都相等,这使得中心点成为一个战略位置。当有多只地鼠同时在t=0时刻出现在不同位置时,根据题解的逻辑,会优先选择(1,1)位置的地鼠敲击,因为它提供了最佳的起始位置优势。如果(1,1)位置没有地鼠,题解没有明确指定选择策略,这可能是一个题解的不足之处。理论上,应该选择一个位置,使得接下来能够最大化敲击数量的策略,但具体策略会依赖于后续地鼠的出现时间和位置。
🦆
在动态规划数组f的初始化中,为什么将moles1数组中添加一个[0, 1, 1]的元素,这个操作有什么特别的意义或用途?
在题解中添加一个[0, 1, 1]的元素到moles1数组是为了确保动态规划的过程中始终包含一个在时刻0、位置(1,1)的地鼠事件,即使在原始数据中没有地鼠在t=0时刻出现在(1,1)位置。这样做的目的是为了简化代码逻辑,使得动态规划的起点明确,始终从中心点开始计算。这个操作保证了动态规划数组f在计算每个事件的最大敲击数时,能够统一地从中心点开始考虑,不需要在代码中另外处理从边缘或其他位置开始的情况。这样的处理通过减少边界条件的复杂性,可以使代码更简洁且易于维护。

相关问题