【LeetCode 818】Race Car

100 篇文章 0 订阅
88 篇文章 0 订阅

题目描述

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.

思路

思路一:
BFS,从当前点开始搜,队列存储到达位置及对应的步数,每次从当前步数能到达的位置扩充。有两种扩充方式,加速和转弯。
注意剪枝,如果当前位置>2target 或者 <0 或者 speed > 2target,就没必要搜索了。
每个位置的转弯也只需要做一次,vis标记。
思路二:
记忆化搜索。搜索到达target的最小步数,如果不是一直前进能到达的位置,有两种可能,先到达后一个整数位置,再往回走。或者先到达前一个,往回走,再往前走。

代码

代码一:BFS

class Solution {
public:
    int racecar(int target) {
        unordered_set<string> vis;
        vis.insert("0_1");
        vis.insert("0_-1"); // pos zhuanxiang
        
        queue<pair<int, int>> que; // pos speed
        que.push({0, 1});
        int step = 0;
        
        while(!que.empty()) {
            int size = que.size();
            while(size--) {
                int pos = que.front().first;
                int speed = que.front().second;
                que.pop();
                
                int pos1 = pos+speed;
                int speed1 = speed*2;
                if (pos1 == target) return step+1;
                if (pos1 < 2*target && abs(speed1) < 2*target && pos1 > 0)
                    que.push({pos1, speed1});
                
                int pos2 = pos;
                int speed2 = speed > 0 ? -1 : 1;
                string cur = to_string(pos2)+"_"+to_string(speed2);
                if (vis.count(cur)) continue;
                que.push({pos2, speed2});
                vis.insert(cur);
            }
            step++;
        }
        
        return -1;
    }
};

代码二:记忆化搜索

class Solution {
public:
    int racecar(int target) {
        dp = vector<int>(target+1);
        return dfs(target);
    }
    
    int dfs(int target) {
        if (dp[target] > 0) return dp[target];
        int n = ceil(log2(target+1)); // up
        if (1<<n == target+1) return dp[target] = n;
        
        // 2^n - 1 > target
        // AnR
        dp[target] = n + 1 + dfs((1<<n)-1-target);
        
        // A(n-1)RAiR
        for (int m=0; m<n-1; ++m) {
            // dp[target] = min(dp[target], n-1+1+m+1+dfs(target- ((1<<(n-1))-1) + (1<<m)-1);
            dp[target] = min(dp[target], n+m+1+dfs(target- (1<<(n-1)) + (1<<m)));
        }
        
        return dp[target];
    }
private:
    vector<int> dp;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值