https://leetcode.com/problems...
Hard
Google, Amazon
第一种解法使用BFS
// bfs
public int racecar(int target) {
int res = 0;
Queue<int[]> q = new LinkedList<>(); // 0: position, 1: speed
Set<String> visited = new HashSet<>();
visited.add("0#1");
q.offer(new int[]{0, 1});
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
int[] cur = q.poll();
assert cur != null;
int pos = cur[0], speed = cur[1];
if (pos == target) return res; // 目标位置,直接返回res
// 1. 尝试加速,更新新位置,新速度
int newPos = pos + speed, newSpeed = speed * 2;
String key = newPos + "#" + newSpeed;
if (!visited.contains(key) && newPos > 0 && newPos < target * 2) {
visited.add(key);
q.offer(new int[]{newPos, newSpeed});
}
// 2. 尝试转向,位置不变,速度根据正负数变成1或者-1
newPos = pos;
newSpeed = speed > 0 ? -1 : 1;
key = newPos + "#" + newSpeed;
if (!visited.contains(key) && newPos > 0 && newPos < target * 2) {
visited.add(key);
q.offer(new int[]{newPos, newSpeed});
}
}
res++;
}
return -1;
}
第二种解法,DP
dp[target] 表示行驶长度为target的距离需要的最小指示个数。dp[target]有两种可能:
- target刚好是由"AAA...A"一共n步到达,也就是一路加速,那么这种走法就是最优选择。
- 如果不是上述情况,就有多种可能:
a.第一次冲过target的时候进行'R'操作,然后反向接近target。此时已经走了n + 1步,并且,和target的距离已经减少到了(2^n - 1 -target),可以递归调用helper函数,继续求解子问题。
b.向前走m步,可以通过递归调用helper函数得到最优值,然后采用策略1.
最终就是min(a, b),也就是a, b两种可能的最小值。
采用dp + memo的方法,每当需要计算一个子问题时,先查表看子问题是否已经被计算过,
如果是,则直接返回;否则,在进行计算,并将结果保存到memo,以便后面计算使用。
public int racecar(int target) {
int[] dp = new int[target + 1];
helper(target, dp);
return dp[target];
}
private int helper(int target, int[] dp) {
// 如果已经计算过,直接返回
if (dp[target] > 0) return dp[target];
int n = (int) (Math.log(target) / Math.log(2)) + 1;
// 如果刚好是第一种情况target = 2^n - 1,则直接放入结果返回
if (1 << n == target + 1) {
dp[target] = n;
} else {
// 是第二种情况,
// 计算a.情况
dp[target] = n + 1 + helper((1 << n) - 1 - target, dp);
// 计算b.情况,并取a,b情况下的最小值对dp[target]进行更新
for (int m = 0; m <= n - 1; m++) {
int cur = (1 << (n - 1) ) - (1 << m);
dp[target] = Math.min(dp[target], n + m + 1 + helper(target - cur, dp));
}
}
return dp[target];
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。