奇偶跳
难度:
标签:
题目描述
代码结果
运行时间: 90 ms, 内存: 19.3 MB
/*
思路:
1. 使用TreeMap和IntStream来实现奇数跳和偶数跳。
2. 维护两个数组odd和even来记录每个索引的奇数跳和偶数跳状态。
3. 通过IntStream倒序遍历数组,从后往前更新奇数跳和偶数跳的状态。
4. 使用TreeMap来找到满足条件的索引。
*/
import java.util.*;
import java.util.stream.IntStream;
public class OddEvenJumpsStream {
public int oddEvenJumps(int[] A) {
int n = A.length;
if (n <= 1) return n;
boolean[] odd = new boolean[n];
boolean[] even = new boolean[n];
odd[n - 1] = true;
even[n - 1] = true;
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(A[n - 1], n - 1);
int count = 1;
IntStream.iterate(n - 2, i -> i >= 0, i -> i - 1).forEach(i -> {
Integer oddJump = map.ceilingKey(A[i]);
Integer evenJump = map.floorKey(A[i]);
if (oddJump != null) {
odd[i] = even[map.get(oddJump)];
}
if (evenJump != null) {
even[i] = odd[map.get(evenJump)];
}
if (odd[i]) count++;
map.put(A[i], i);
});
return count;
}
}
解释
方法:
本题解采用动态规划与单调栈的结合来解决奇偶跳的问题。首先,为了找到每个位置的奇数跳和偶数跳的目的地,我们使用单调栈两次:一次处理奇数跳,一次处理偶数跳。奇数跳需要找到右边第一个不小于当前值的最小值,而偶数跳需要找到右边第一个不大于当前值的最大值。这可以通过对数组的索引排序,并以此顺序遍历数组,使用单调栈完成。之后,使用动态规划自后向前计算,对于每个位置,记录其奇数跳和偶数跳是否能到达数组的末尾。最后,统计可以通过奇数跳到达末尾的起始位置数量,即为答案。
时间复杂度:
O(N log N)
空间复杂度:
O(N)
代码细节讲解
🦆
在单调栈的使用中,为什么要选择在处理奇数跳时按照数组值的升序排序,而在处理偶数跳时按照降序排序?
▷🦆
在构造奇数跳和偶数跳目的地的函数`make`中,为什么在遇到idx大于栈顶元素时,要进行弹栈操作?
▷🦆
代码中的`Odp`和`Edp`数组分别表示什么意义,并且这两个数组是如何交互以确定最终的路径可行性的?
▷🦆
动态规划在这个问题中是如何从后向前计算的,具体是基于什么样的逻辑来更新`Odp`和`Edp`数组的?
▷