Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/818.html

818. Race Car

Level

Hard

Description

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.

Note:

  • 1 <= target <= 10000.

Solution

Use dynamic programming. Create an array dp of length Math.max(target + 3, target * 2), where dp[i] represents the length of the shortest sequence of instructions to get to position i. Initialize dp[0] = 0, dp[1] = 1 and dp[2] = 4.

If i is 2^k - 1 for some k, then dp[i] = k. Otherwise, suppose 2^(k - 1) <= i < 2^k for some positive integer k, it is possible to reach 2^(k - 1) - 1 first and then use instructions with “R” to reach i, or reach 2^k - 1 first and then use instructions with “R” to reach i. Calculate the minimum length accordingly.

  • class Solution {
        public int racecar(int target) {
            int[] dp = new int[Math.max(target + 3, target * 2)];
            Arrays.fill(dp, Integer.MAX_VALUE);
            dp[0] = 0;
            dp[1] = 1;
            dp[2] = 4;
            for (int i = 3; i <= target; i++) {
                int bits = (int) (Math.log(i) / Math.log(2)) + 1;
                if (i == (1 << bits) - 1)
                    dp[i] = bits;
                else {
                    for (int j = 0; j < bits - 1; j++)
                        dp[i] = Math.min(dp[i], dp[i - (1 << (bits - 1)) + (1 << j)] + bits - 1 + j + 2);
                    if ((1 << bits) - 1 - i < i)
                        dp[i] = Math.min(dp[i], dp[(1 << bits) - 1 - i] + bits + 1);
                }
            }
            return dp[target];
        }
    }
    
  • // OJ: https://leetcode.com/problems/race-car/
    // Time: O(?)
    // Space: O(?)
    // Ref: https://leetcode.com/problems/race-car/discuss/124312/Javascript-Python3-C%2B%2B-.-BFS-solutions
    class Solution {
    public:
        int racecar(int target) {
            queue<array<int, 2>> q;
            q.push({0, 1});
            unordered_map<int, unordered_set<int>> seen;
            seen[0].insert(1);
            int step = 0;
            while (true) {
                int cnt = q.size();
                while (cnt--) {
                    auto [pos, speed] = q.front();
                    q.pop();
                    if (pos == target) return step;
                    vector<array<int, 2>> cand;
                    if (abs(target - (pos + speed)) < target) cand.push_back({ pos + speed, 2 * speed }); // Only continue moving in the current direction if doing so reduces the distance.
                    cand.push_back({ pos, speed < 0 ? 1 : - 1 }); // reverse direction
                    for (auto &[pos, speed] : cand) {
                        if (seen[pos].count(speed)) continue;
                        seen[pos].insert(speed);
                        q.push({pos, speed});
                    }
                }
                ++step;
            }
            return -1;
        }
    };
    
  • class Solution:
        def racecar(self, target: int) -> int:
            dp = [0] * (target + 1)
            for i in range(1, target + 1):
                k = i.bit_length()
                if i == 2**k - 1:
                    dp[i] = k
                    continue
                dp[i] = dp[2**k - 1 - i] + k + 1
                for j in range(k - 1):
                    dp[i] = min(dp[i], dp[i - (2 ** (k - 1) - 2**j)] + k - 1 + j + 2)
            return dp[target]
    
    
    
  • func racecar(target int) int {
    	dp := make([]int, target+1)
    	for i := 1; i <= target; i++ {
    		k := bits.Len(uint(i))
    		if i == (1<<k)-1 {
    			dp[i] = k
    			continue
    		}
    		dp[i] = dp[(1<<k)-1-i] + k + 1
    		for j := 0; j < k; j++ {
    			dp[i] = min(dp[i], dp[i-(1<<(k-1))+(1<<j)]+k-1+j+2)
    		}
    	}
    	return dp[target]
    }
    
    func min(a, b int) int {
    	if a < b {
    		return a
    	}
    	return b
    }
    

All Problems

All Solutions