问题1: 给你一个整数 n,一个二维整数数组 restrictions,以及一个长度为 n - 1 ...

Erstellt am: 3. Januar 2026

Beantwortet mit GPT-5.2 Thinking von Chat01

Frage

问题1:
给你一个整数 n,一个二维整数数组 restrictions,以及一个长度为 n - 1 的整数数组 diff。你的任务是构造一个长度为 n 的序列,记为 a[0], a[1], ..., a[n - 1],使其满足以下条件:

a[0] 为 0。
序列中的所有元素都是 非负整数。
对于每个下标 i (0 <= i <= n - 2),满足 abs(a[i] - a[i + 1]) <= diff[i]。
对于每个 restrictions[i] = [idx, maxVal],序列中位置 idx 的值不得超过 maxVal(即 a[idx] <= maxVal)。
你的目标是在满足上述所有条件的情况下,构造一个合法的序列并 最大化 该序列中的 最大 值。

返回一个整数,表示最优序列中出现的 最大 值。

示例 1:

输入: n = 10, restrictions = [[3,1],[8,1]], diff = [2,2,3,1,4,5,1,1,2]

输出: 6

解释:

序列 a = [0, 2, 4, 1, 2, 6, 2, 1, 1, 3] 满足给定的限制条件(a[3] <= 1 且 a[8] <= 1)。
序列中的最大值为 6。
示例 2:

输入: n = 8, restrictions = [[3,2]], diff = [3,5,2,4,2,3,1]

输出: 12

解释:

序列 a = [0, 3, 3, 2, 6, 8, 11, 12] 满足给定的限制条件(a[3] <= 2)。
序列中的最大值为 12。

提示:

2 <= n <= 10^5
1 <= restrictions.length <= n - 1
restrictions[i].length == 2
restrictions[i] = [idx, maxVal]
1 <= idx < n
1 <= maxVal <= 10^6
diff.length == n - 1
1 <= diff[i] <= 10
restrictions[i][0] 的值是唯一的。

class Solution {
public int findMaxVal(int n, int[][] restrictions, int[] diff) {

}

}

问题2:
给你一个大小为 n 的字符串数组 grid,其中每个字符串 grid[i] 的长度为 m。字符 grid[i][j] 是以下符号之一:

'.':该单元格可用。
'#':该单元格被阻塞。
你想计算攀爬 grid 的不同路径数量。每条路径必须从最后一行(第 n - 1 行)的任何一个格子开始,并在第一行(第 0 行)结束。

但是,路径受到以下限制:

你只能从一个可用单元格移动到 另一个 可用单元格。
每次移动的 欧几里得距离至多为 d,其中 d 是给定的整数参数。两个单元格 (r1, c1) 和 (r2, c2) 之间的欧几里得距离为 sqrt((r1 - r2)2 + (c1 - c2)2)。
每次移动要么留在同一行,要么移动到正上方的一行(从第 r 行到第 r - 1 行)。
你不能连续两次移动都留在同一行。如果你在一次移动中留在同一行(且该移动不是最后一次移动),你的下一次移动必须进入上一行。
返回一个整数,表示此类路径的数量。由于答案可能很大,请将其对109 + 7取余后返回。

示例 1:

输入: grid = ["..","#."], d = 1

输出: 2

解释:

我们按顺序标记路径中访问的单元格,从 1 开始。两条路径分别是:

.2
#1
32
#1
我们可以从单元格 (1, 1) 移动到单元格 (0, 1),因为欧几里得距离为 sqrt((1 - 0)2 + (1 - 1)2) = sqrt(1) <= d。

但是,我们不能从单元格 (1, 1) 移动到单元格 (0, 0),因为欧几里得距离为 sqrt((1 - 0)2 + (1 - 0)2) = sqrt(2) > d。

示例 2:

输入: grid = ["..","#."], d = 2

输出: 4

解释:

示例 1 中的两条路径也符合条件。另外两条路径是:

#1
23
#1
注意,我们可以从 (1, 1) 移动到 (0, 0),因为欧几里得距离 sqrt(2) <= d。

示例 3:

输入: grid = ["#"], d = 750

输出: 0

解释:

我们无法选择任何单元格作为起始单元格。因此,不存在路径。

示例 4:

输入: grid = [".."], d = 1

输出: 4

解释:

可能的路径为:

.1
1.
12
21

提示:

1 <= n == grid.length <= 750
1 <= m == grid[i].length <= 750
grid[i][j] 为 '.' 或 '#'。
1 <= d <= 750

class Solution {
public int numberOfRoutes(String[] grid, int d) {

}

} 解决这两个问题,通过所有例子,并且不能超时

Gedanke

Breaking down algorithm for building height problem

Alright, I need to solve this algorithm that’s similar to LeetCode 1840, "Maximum Building Height." The idea is to maximize the height sequence where adjacent differences aren’t too big. I’ll compute upper bounds by propagating the restrictions from both directions. The approach is essentially determining the maximal height respecting the slope constraints and limits.

Maximizing height under constraints

I need to maximize the height sequence subject to constraints: the difference between consecutive elements needs to be bounded by a given value. I’ll treat these bounds as caps and optimize the heights by choosing the largest values feasible at each index, considering propagation across constraints. The goal is to maximize the general achievable height.

Maximizing values under constraints

I’m thinking that maximizing the values could lead to violations of the constraints, as pushing one value high might cause neighbors to exceed their caps. To avoid this, I could calculate the maximum feasible value at each point considering the upper bounds. The goal is balancing the sequence while respecting the constraints.

Determining maximal height given constraints

To maximize the height at each point, I need to consider the caps on neighboring points, as well as the distance constraints. Heights should be set to the highest possible value without violating any caps. The overall approach is to set each height as the minimum of all constraints: the caps and the reachable distance from other capped points.

Verifying feasibility of maximum sequence

I’m constructing a sequence that respects the height constraints and difference limits. I’ll define upper bounds using a minimum of capped values and distances, ensuring Lipschitz consistency. The sequence should meet all constraints without exceeding caps, and the maximum achievable value will be the highest upper bound at any index. To compute this efficiently, I need to check feasibility for large inputs, ensuring performance for up to 100,000 values.

Optimizing cap calculation efficiency

I’m trying to improve the algorithm used to compute the maximal possible values efficiently. By adjusting the method for variable distances and restrictions, I can treat the restrictions as points along a line, compute the minimal upper envelope using a forward and backward pass, and avoid recalculating for every index, allowing a more efficient solution.

Ensuring minimal upper bounds with two passes

To ensure the minimal upper bounds work, I verify that the constraints propagate correctly from both directions. The forward pass handles the influence of left caps, and the backward pass adjusts values from the right. It's essentially similar to computing a 1D shortest path, where two sweeps handle the constraints efficiently.

Maximizing the possible upper bound

To handle variable weights, we use dynamic programming to compute forward and backward minimums, adjusting caps with each pass. If no caps are present, the maximum value is constrained by the distance from 0 to the last index. The final answer is the maximum possible upper bound, computed in O(n), ensuring all constraints are met.

Implementing dynamic programming for bounds calculation

The approach to calculating the upper bound with dynamic programming requires forward and backward passes, adjusting caps at restrictions and distances. This gives an O(n) solution with memory complexity O(n). Java implementation utilizes arrays to store caps and computes the upper bounds while using long integers to avoid overflow.

Calculating paths with constraints on same-row moves

For a grid with one row, paths start and end in the same row, but you can only make one same-row move because two consecutive same-row moves are not allowed unless the last move. For n=1, each cell is a valid path, and you can count the allowed movements to get a total of 4 paths.

Modeling pathfinding with constraints and conditions

I’m considering how to model the pathfinding where each step either stays in the same row or moves up, following an upwards path while decrementing row values. The challenge is to compute these paths efficiently while respecting constraints on staying within the same row or moving to another cell. I need to optimize the solution, given grid size limitations.

Applying dynamic programming with path constraints

I’m developing a dynamic programming solution with pathfinding while accounting for constraints like no consecutive stays and distance restrictions. I’ll compute the number of possible paths row by row, storing results in two states: "up" (U) and "stay" (S). Each state's transitions will depend on the availability and distance to neighboring cells.

Refining dynamic programming grid implementation

I’m working on optimizing the grid traversal with dynamic programming. In each row, we calculate the number of ways to move up or stay. The strategy involves prefix sums for efficiency. I'll handle boundary cases, blocked cells, and ensure the result counts paths with modulo constraints.

Thought for 2m 53s

Antwort

下面给出两个题都可过所有样例且不会超时的做法与 Java 代码(两题是两个独立的 Solution,提交时分别提交对应那题即可)。


问题 1:最大化序列最大值

核心思路(O(n))

把每个位置的“允许最大值”当作上界 cap[i](无约束则为 INF,且 cap[0]=0)。

相邻约束 |a[i]-a[i+1]|<=diff[i] 等价于上界传播:

  • 从左到右:a[i] <= a[i-1] + diff[i-1]
  • 从右到左:a[i] <= a[i+1] + diff[i]

做两遍松弛后得到每个位置的最大可取上界 upper[i],那么取 a[i]=upper[i] 本身就是合法序列,并且其最大值就是答案。

时间 O(n),空间 O(n)。

java
import java.util.*; class Solution { public int findMaxVal(int n, int[][] restrictions, int[] diff) { final int INF = 1_000_000_000; int[] cap = new int[n]; Arrays.fill(cap, INF); cap[0] = 0; for (int[] r : restrictions) { cap[r[0]] = r[1]; } int[] upper = new int[n]; upper[0] = 0; // Left -> Right: upper[i] = min(cap[i], upper[i-1] + diff[i-1]) for (int i = 1; i < n; i++) { int v = upper[i - 1] + diff[i - 1]; upper[i] = Math.min(cap[i], v); } // Right -> Left: upper[i] = min(upper[i], upper[i+1] + diff[i]) for (int i = n - 2; i >= 0; i--) { int v = upper[i + 1] + diff[i]; if (v < upper[i]) upper[i] = v; } int ans = 0; for (int i = 0; i < n; i++) ans = Math.max(ans, upper[i]); return ans; } }

问题 2:攀爬路径计数(带“不能连续同层移动”)

状态设计(O(n*m))

对每个格子 (r,c) 维护两种状态:

  • U[r][c]:到达 (r,c) 时,上一步不是同层移动(可以选择同层或上移)
  • S[r][c]:到达 (r,c) 时,上一步是同层移动(下一步若还没结束则必须上移)

转移:

  1. 上移:从 rr-1,水平偏移满足
    (dr=1) => 1 + dx^2 <= d^2 => |dx| <= floor(sqrt(d^2-1)) = du
    所以:
  • U[r-1][c] += sum_{k in [c-du, c+du]} (U[r][k] + S[r][k])
  1. 同层移动:从 U[r] 走到同一行 S[r],水平偏移 |dx|<=d,且必须是另一个格子(排除自身):
  • S[r][c] += sum_{k in [c-d, c+d]} U[r][k] - U[r][c]

两种“区间求和”都用前缀和做到每行 O(m),总 O(nm)(≤ 750750 很稳)。

起点:最后一行任意 '.' 作为开始,相当于 U[last][c]=1
答案:第一行所有 '.'U[0][c]+S[0][c] 之和(因为可以在第一行结束,也可以最后一步做一次同层移动后结束)。

java
import java.util.*; class Solution { private static final int MOD = 1_000_000_007; public int numberOfRoutes(String[] grid, int d) { int n = grid.length; int m = grid[0].length(); // du = floor(sqrt(d^2 - 1)) for moves to row-1 long sq = 1L * d * d - 1; int du = (sq <= 0) ? 0 : (int) Math.floor(Math.sqrt(sq)); int[] Ubelow = new int[m]; int[] Sbelow = new int[m]; for (int r = n - 1; r >= 0; r--) { int[] Ucur = new int[m]; int[] Scur = new int[m]; String row = grid[r]; if (r == n - 1) { // start positions for (int c = 0; c < m; c++) { Ucur[c] = (row.charAt(c) == '.') ? 1 : 0; } } else { // compute Ucur from row r+1 (Ubelow, Sbelow) using interval sums with radius du int[] T = new int[m]; for (int c = 0; c < m; c++) { int v = Ubelow[c] + Sbelow[c]; if (v >= MOD) v -= MOD; T[c] = v; } int[] pref = buildPrefix(T); for (int c = 0; c < m; c++) { if (row.charAt(c) == '#') { Ucur[c] = 0; } else { Ucur[c] = intervalSum(pref, c - du, c + du, m); } } } // compute Scur from Ucur within same row using radius d, excluding self int[] prefU = buildPrefix(Ucur); for (int c = 0; c < m; c++) { if (row.charAt(c) == '#') { Scur[c] = 0; } else { int sum = intervalSum(prefU, c - d, c + d, m); int val = sum - Ucur[c]; if (val < 0) val += MOD; Scur[c] = val; } } Ubelow = Ucur; Sbelow = Scur; } // now Ubelow/Sbelow correspond to row 0 long ans = 0; for (int c = 0; c < grid[0].length(); c++) { if (grid[0].charAt(c) == '.') { ans += Ubelow[c]; ans += Sbelow[c]; ans %= MOD; } } return (int) ans; } private int[] buildPrefix(int[] arr) { int m = arr.length; int[] pref = new int[m + 1]; for (int i = 0; i < m; i++) { int v = pref[i] + arr[i]; if (v >= MOD) v -= MOD; pref[i + 1] = v; } return pref; } // inclusive [l, r] private int intervalSum(int[] pref, int l, int r, int m) { if (l < 0) l = 0; if (r >= m) r = m - 1; if (l > r) return 0; int res = pref[r + 1] - pref[l]; if (res < 0) res += MOD; return res; } }

如果你希望我把两题代码合并成一个文件(避免两个 Solution 类名冲突),我也可以给一个“统一类名 + 两个方法”的版本。

Diesen Q&A teilen