818. Race Car
Your car starts at position 0 and speed +1 on an infinite number line. (Your car can go into negative positions.)
Your car drives automatically according to a sequence of instructions A (accelerate) and R (reverse).
When you get an instruction "A", your car does the following: position += speed, speed *= 2
.
When you get an instruction "R", your car does the following: if your speed is positive then speed = -1
, otherwise speed = 1
. (Your position stays the same.)
For example, after commands "AAR", your car goes to positions 0->1->3->3, and your speed goes to 1->2->4->-1.
Now for some target position, say the length of the shortest sequence of instructions to get there.
Example 1: Input: target = 3 Output: 2 Explanation: The shortest instruction sequence is "AA". Your position goes from 0->1->3.
Example 2: Input: target = 6 Output: 5 Explanation: The shortest instruction sequence is "AAARA". Your position goes from 0->1->3->7->7->6.
Approach #1: C++. [DFS]
class Solution { public: int racecar(int target) { queue<pair<int, int>> q; q.push({0, 1}); unordered_set<string> v; v.insert("0_1"); v.insert("0_-1"); int steps = 0; while (!q.empty()) { int size = q.size(); while (size--) { auto p = q.front(); q.pop(); int pos = p.first; int speed = p.second; { int pos1 = pos + speed; int speed1 = speed * 2; pair<int, int> p1{pos1, speed1}; if (pos1 == target) return steps+1; if (p1.first > 0 && p1.first < 2 * target) q.push(p1); } { int speed2 = speed > 0 ? -1 : 1; pair<int, int> p2{pos, speed2}; string key2 = to_string(pos) + "_" + to_string(speed2); if (!v.count(key2)) { q.push(p2); v.insert(key2); } } } steps++; } return -1; } };
Approach #2: Java. [DP]
class Solution { private static int[][] m; public int racecar(int target) { if (m == null) { final int kMaxT = 10000; m = new int[kMaxT + 1][2]; for (int t = 1; t <= kMaxT; ++t) { int n = (int)Math.ceil(Math.log(t + 1) / Math.log(2)); if (1 << n == t + 1) { m[t][0] = n; m[t][1] = n + 1; continue; } int l = (1 << n) - 1 - t; m[t][0] = n + 1 + Math.min(m[l][1], m[l][0] + 1); m[t][1] = n + 1 + Math.min(m[l][0], m[l][1] + 1); for (int i = 1; i < t; ++i) { for (int d = 0; d <= 1; ++d) { m[t][d] = Math.min(m[t][d], Math.min( m[i][0] + 2 + m[t-i][d], m[i][1] + 1 + m[t-i][d])); } } } } return Math.min(m[target][0], m[target][1]); } }
Approach #3: Python. [DP]
class Solution(object): def __init__(self): self.dp = {0: 0} def racecar(self, t): """ :type target: int :rtype: int """ if t in self.dp: return self.dp[t] n = t.bit_length() if 2**n - 1 == t: self.dp[t] = n else: self.dp[t] = self.racecar(2**n - 1 - t) + n + 1 for m in range(n-1): self.dp[t] = min(self.dp[t], self.racecar(t - 2**(n-1) + 2**m) + n + m + 1) return self.dp[t]
Analysis:
http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-818-race-car/