列表

详情


818. 赛车

你的赛车可以从位置 0 开始,并且速度为 +1 ,在一条无限长的数轴上行驶。赛车也可以向负方向行驶。赛车可以按照由加速指令 'A' 和倒车指令 'R' 组成的指令序列自动行驶。

例如,在执行指令 "AAR" 后,赛车位置变化为 0 --> 1 --> 3 --> 3 ,速度变化为 1 --> 2 --> 4 --> -1

给你一个目标位置 target ,返回能到达目标位置的最短指令序列的长度。

 

示例 1:

输入:target = 3
输出:2
解释:
最短指令序列是 "AA" 。
位置变化 0 --> 1 --> 3 。

示例 2:

输入:target = 6
输出:5
解释:
最短指令序列是 "AAARA" 。
位置变化 0 --> 1 --> 3 --> 7 --> 7 --> 6 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int racecar(int target) { } };

golang 解法, 执行用时: 4 ms, 内存消耗: 2.2 MB, 提交时间: 2023-09-28 23:52:20

import "math"

func racecar(target int) int {
	t := make([]int, target+1)
	for i := 1; i <= target; i++ {
		t[i] = math.MaxInt64
		j, c := 1, 1
		for ; j < i; j = (1 << uint(c)) - 1 {
			for k, c1 := 0, 0; k < j; k = (1 << uint(c1)) - 1 {
				t1 := c + c1 + 2 + t[i-j+k]
				if t1 < t[i] {
					t[i] = t1
				}
				c1++
			}
			c++
		}
		t1 := c
		if i != j {
			t1 += 1 + t[j-i]
		}
		if t1 < t[i] {
			t[i] = t1
		}
	}
	return t[target]
}

java 解法, 执行用时: 7 ms, 内存消耗: 38 MB, 提交时间: 2023-09-28 23:51:34

class Solution {
    public int racecar(int target) {
        //处理边界
        if (target <= 0) {
            return 0;
        }

        int[] dp = new int[target + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);

        for (int i = 1; i <= target; i++) {
            //先向前走 forward 步
            for (int forward = 1; (1 << forward) - 1 < 2 * i; forward++) {
                //向前走了forwardDistance
                int forwardDistance = (1 << forward) - 1;
                //对应第一种情况,走了forward步直接到达i
                if (forwardDistance == i) {
                    dp[i] = forward;
                } else if (forwardDistance > i) { //对应第二种情况,越过了i
                    // +1 是因为回头需要一个R指令
                    dp[i] = Math.min(dp[i], 
                            forward + 1 + dp[forwardDistance - i]);
                } else { //对应第三种情况,没有越过i
                    //先回头走backward步
                    for (int backward = 0; backward < forward; backward++) {
                        int backwardDistance = (1 << backward) - 1;
                        //第一个+1是还没到达i,先回头,使用一个R
                        //第二个+1是回头走了backwardDistance,再使用R回头走向i
                        dp[i] = Math.min(dp[i], 
                                forward + 1 + backward + 1 + dp[i - forwardDistance + backwardDistance]);
                    }
                }
            }
        }
        return dp[target];
    }
}

java 解法, 执行用时: 4 ms, 内存消耗: 38.3 MB, 提交时间: 2023-09-28 23:44:30

class Solution {
    public int racecar(int target) {
        int[] dp = new int[target + 3];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0; dp[1] = 1; dp[2] = 4;

        for (int t = 3; t <= target; ++t) {
            int k = 32 - Integer.numberOfLeadingZeros(t);
            if (t == (1<<k) - 1) {
                dp[t] = k;
                continue;
            }
            for (int j = 0; j < k-1; ++j)
                dp[t] = Math.min(dp[t], dp[t - (1<<(k-1)) + (1<<j)] + k-1 + j + 2);
            if ((1<<k) - 1 - t < t)
                dp[t] = Math.min(dp[t], dp[(1<<k) - 1 - t] + k + 1);
        }

        return dp[target];  
    }
}

python3 解法, 执行用时: 292 ms, 内存消耗: 16.1 MB, 提交时间: 2023-09-28 23:44:14

class Solution:
    # dp[x] 表示到达位置 x 的最短指令长度
    def racecar(self, target: int) -> int:
        dp = [0, 1, 4] + [float('inf')] * target
        for t in range(3, target + 1):
            k = t.bit_length()
            if t == 2**k - 1:
                dp[t] = k
                continue
            for j in range(k - 1):
                dp[t] = min(dp[t], dp[t - 2**(k - 1) + 2**j] + k - 1 + j + 2)
            if 2**k - 1 - t < t:
                dp[t] = min(dp[t], dp[2**k - 1 - t] + k + 1)
        return dp[target]

python3 解法, 执行用时: 920 ms, 内存消耗: 20 MB, 提交时间: 2023-09-28 23:42:31

class Solution:
    def racecar(self, target: int) -> int:
        K = target.bit_length() + 1
        barrier = 1 << K
        pq = [(0, target)]
        dist = [float('inf')] * (2 * barrier + 1)
        dist[target] = 0

        while pq:
            steps, targ = heapq.heappop(pq)
            if dist[targ] > steps: continue

            for k in range(K+1):
                walk = (1 << k) - 1
                steps2, targ2 = steps + k + 1, walk - targ
                if walk == targ: steps2 -= 1 #No "R" command if already exact

                if abs(targ2) <= barrier and steps2 < dist[targ2]:
                    heapq.heappush(pq, (steps2, targ2))
                    dist[targ2] = steps2

        return dist[0]

java 解法, 执行用时: 82 ms, 内存消耗: 43 MB, 提交时间: 2023-09-28 23:42:01

// Djikstra 
class Solution {
    public int racecar(int target) {
        int K = 33 - Integer.numberOfLeadingZeros(target - 1);
        int barrier = 1 << K;
        int[] dist = new int[2 * barrier + 1];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[target] = 0;

        PriorityQueue<Node> pq = new PriorityQueue<Node>(
            (a, b) -> a.steps - b.steps);
        pq.offer(new Node(0, target));

        while (!pq.isEmpty()) {
            Node node = pq.poll();
            int steps = node.steps, targ1 = node.target;
            if (dist[Math.floorMod(targ1, dist.length)] > steps) continue;

            for (int k = 0; k <= K; ++k) {
                int walk = (1 << k) - 1;
                int targ2 = walk - targ1;
                int steps2 = steps + k + (targ2 != 0 ? 1 : 0);

                if (Math.abs(targ2) <= barrier && steps2 < dist[Math.floorMod(targ2, dist.length)]) {
                    pq.offer(new Node(steps2, targ2));
                    dist[Math.floorMod(targ2, dist.length)] = steps2;
                }
            }
        }

        return dist[0];
    }
}

class Node {
    int steps, target;
    Node(int s, int t) {
        steps = s;
        target = t;
    }
}

上一题